Merge branches 'clk-ingenic', 'clk-mtk-mux', 'clk-qcom-sdm845-pcie', 'clk-mtk-crit...
authorStephen Boyd <sboyd@kernel.org>
Fri, 8 Mar 2019 18:29:30 +0000 (10:29 -0800)
committerStephen Boyd <sboyd@kernel.org>
Fri, 8 Mar 2019 18:29:30 +0000 (10:29 -0800)
* clk-ingenic:
  clk: ingenic: Remove set but not used variable 'enable'
  clk: ingenic: Fix doc of ingenic_cgu_div_info
  clk: ingenic: Fix round_rate misbehaving with non-integer dividers
  clk: ingenic: jz4740: Fix gating of UDC clock

* clk-mtk-mux:
  clk: mediatek: using CLK_MUX_ROUND_CLOSEST for the clock of dpi1_sel
  clk: mediatek: add MUX_GATE_FLAGS_2

* clk-qcom-sdm845-pcie:
  clk: qcom: gcc-sdm845: Define parent of PCIe PIPE clocks

* clk-mtk-crit:
  clk: mediatek: Mark bus and DRAM related clocks as critical
  clk: mediatek: Add flags to mtk_gate
  clk: mediatek: Add MUX_FLAGS macro

* clk-mtk:
  clk: mediatek: correct cpu clock name for MT8173 SoC

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

index e6080f5..bc2ffb2 100644 (file)
@@ -72,6 +72,10 @@ ForEachMacros:
   - 'apei_estatus_for_each_section'
   - 'ata_for_each_dev'
   - 'ata_for_each_link'
+  - '__ata_qc_for_each'
+  - 'ata_qc_for_each'
+  - 'ata_qc_for_each_raw'
+  - 'ata_qc_for_each_with_internal'
   - 'ax25_for_each'
   - 'ax25_uid_for_each'
   - 'bio_for_each_integrity_vec'
@@ -85,6 +89,7 @@ ForEachMacros:
   - 'blk_queue_for_each_rl'
   - 'bond_for_each_slave'
   - 'bond_for_each_slave_rcu'
+  - 'bpf_for_each_spilled_reg'
   - 'btree_for_each_safe128'
   - 'btree_for_each_safe32'
   - 'btree_for_each_safe64'
@@ -103,6 +108,8 @@ ForEachMacros:
   - 'drm_atomic_crtc_for_each_plane'
   - 'drm_atomic_crtc_state_for_each_plane'
   - 'drm_atomic_crtc_state_for_each_plane_state'
+  - 'drm_atomic_for_each_plane_damage'
+  - 'drm_connector_for_each_possible_encoder'
   - 'drm_for_each_connector_iter'
   - 'drm_for_each_crtc'
   - 'drm_for_each_encoder'
@@ -121,11 +128,21 @@ ForEachMacros:
   - 'for_each_bio'
   - 'for_each_board_func_rsrc'
   - 'for_each_bvec'
+  - 'for_each_card_components'
+  - 'for_each_card_links'
+  - 'for_each_card_links_safe'
+  - 'for_each_card_prelinks'
+  - 'for_each_card_rtds'
+  - 'for_each_card_rtds_safe'
+  - 'for_each_cgroup_storage_type'
   - 'for_each_child_of_node'
   - 'for_each_clear_bit'
   - 'for_each_clear_bit_from'
   - 'for_each_cmsghdr'
   - 'for_each_compatible_node'
+  - 'for_each_component_dais'
+  - 'for_each_component_dais_safe'
+  - 'for_each_comp_order'
   - 'for_each_console'
   - 'for_each_cpu'
   - 'for_each_cpu_and'
@@ -133,6 +150,10 @@ ForEachMacros:
   - 'for_each_cpu_wrap'
   - 'for_each_dev_addr'
   - 'for_each_dma_cap_mask'
+  - 'for_each_dpcm_be'
+  - 'for_each_dpcm_be_rollback'
+  - 'for_each_dpcm_be_safe'
+  - 'for_each_dpcm_fe'
   - 'for_each_drhd_unit'
   - 'for_each_dss_dev'
   - 'for_each_efi_memory_desc'
@@ -149,6 +170,7 @@ ForEachMacros:
   - 'for_each_iommu'
   - 'for_each_ip_tunnel_rcu'
   - 'for_each_irq_nr'
+  - 'for_each_link_codecs'
   - 'for_each_lru'
   - 'for_each_matching_node'
   - 'for_each_matching_node_and_match'
@@ -160,6 +182,7 @@ ForEachMacros:
   - 'for_each_mem_range_rev'
   - 'for_each_migratetype_order'
   - 'for_each_msi_entry'
+  - 'for_each_msi_entry_safe'
   - 'for_each_net'
   - 'for_each_netdev'
   - 'for_each_netdev_continue'
@@ -183,12 +206,14 @@ ForEachMacros:
   - 'for_each_node_with_property'
   - 'for_each_of_allnodes'
   - 'for_each_of_allnodes_from'
+  - 'for_each_of_cpu_node'
   - 'for_each_of_pci_range'
   - 'for_each_old_connector_in_state'
   - 'for_each_old_crtc_in_state'
   - 'for_each_oldnew_connector_in_state'
   - 'for_each_oldnew_crtc_in_state'
   - 'for_each_oldnew_plane_in_state'
+  - 'for_each_oldnew_plane_in_state_reverse'
   - 'for_each_oldnew_private_obj_in_state'
   - 'for_each_old_plane_in_state'
   - 'for_each_old_private_obj_in_state'
@@ -206,14 +231,17 @@ ForEachMacros:
   - 'for_each_process'
   - 'for_each_process_thread'
   - 'for_each_property_of_node'
+  - 'for_each_registered_fb'
   - 'for_each_reserved_mem_region'
-  - 'for_each_resv_unavail_range'
+  - 'for_each_rtd_codec_dai'
+  - 'for_each_rtd_codec_dai_rollback'
   - 'for_each_rtdcom'
   - 'for_each_rtdcom_safe'
   - 'for_each_set_bit'
   - 'for_each_set_bit_from'
   - 'for_each_sg'
   - 'for_each_sg_page'
+  - 'for_each_sibling_event'
   - '__for_each_thread'
   - 'for_each_thread'
   - 'for_each_zone'
@@ -251,6 +279,8 @@ ForEachMacros:
   - 'hlist_nulls_for_each_entry_from'
   - 'hlist_nulls_for_each_entry_rcu'
   - 'hlist_nulls_for_each_entry_safe'
+  - 'i3c_bus_for_each_i2cdev'
+  - 'i3c_bus_for_each_i3cdev'
   - 'ide_host_for_each_port'
   - 'ide_port_for_each_dev'
   - 'ide_port_for_each_present_dev'
@@ -267,11 +297,14 @@ ForEachMacros:
   - 'kvm_for_each_memslot'
   - 'kvm_for_each_vcpu'
   - 'list_for_each'
+  - 'list_for_each_codec'
+  - 'list_for_each_codec_safe'
   - 'list_for_each_entry'
   - 'list_for_each_entry_continue'
   - 'list_for_each_entry_continue_rcu'
   - 'list_for_each_entry_continue_reverse'
   - 'list_for_each_entry_from'
+  - 'list_for_each_entry_from_rcu'
   - 'list_for_each_entry_from_reverse'
   - 'list_for_each_entry_lockless'
   - 'list_for_each_entry_rcu'
@@ -291,6 +324,7 @@ ForEachMacros:
   - 'media_device_for_each_intf'
   - 'media_device_for_each_link'
   - 'media_device_for_each_pad'
+  - 'nanddev_io_for_each_page'
   - 'netdev_for_each_lower_dev'
   - 'netdev_for_each_lower_private'
   - 'netdev_for_each_lower_private_rcu'
@@ -357,12 +391,14 @@ ForEachMacros:
   - 'sk_nulls_for_each'
   - 'sk_nulls_for_each_from'
   - 'sk_nulls_for_each_rcu'
+  - 'snd_array_for_each'
   - 'snd_pcm_group_for_each_entry'
   - 'snd_soc_dapm_widget_for_each_path'
   - 'snd_soc_dapm_widget_for_each_path_safe'
   - 'snd_soc_dapm_widget_for_each_sink_path'
   - 'snd_soc_dapm_widget_for_each_source_path'
   - 'tb_property_for_each'
+  - 'tcf_exts_for_each_action'
   - 'udp_portaddr_for_each_entry'
   - 'udp_portaddr_for_each_entry_rcu'
   - 'usb_hub_for_each_child'
@@ -371,6 +407,11 @@ ForEachMacros:
   - 'v4l2_m2m_for_each_dst_buf_safe'
   - 'v4l2_m2m_for_each_src_buf'
   - 'v4l2_m2m_for_each_src_buf_safe'
+  - 'virtio_device_for_each_vq'
+  - 'xa_for_each'
+  - 'xas_for_each'
+  - 'xas_for_each_conflict'
+  - 'xas_for_each_marked'
   - 'zorro_for_each_dev'
 
 #IncludeBlocks: Preserve # Unknown to clang-format-5.0
diff --git a/CREDITS b/CREDITS
index e818eb6..0175098 100644 (file)
--- a/CREDITS
+++ b/CREDITS
@@ -842,10 +842,9 @@ D: ax25-utils maintainer.
 
 N: Helge Deller
 E: deller@gmx.de
-E: hdeller@redhat.de
-D: PA-RISC Linux hacker, LASI-, ASP-, WAX-, LCD/LED-driver
-S: Schimmelsrain 1
-S: D-69231 Rauenberg
+W: http://www.parisc-linux.org/
+D: PA-RISC Linux architecture maintainer
+D: LASI-, ASP-, WAX-, LCD/LED-driver
 S: Germany
 
 N: Jean Delvare
@@ -1361,7 +1360,7 @@ S: Stellenbosch, Western Cape
 S: South Africa
 
 N: Grant Grundler
-E: grundler@parisc-linux.org
+E: grantgrundler@gmail.com
 W: http://obmouse.sourceforge.net/
 W: http://www.parisc-linux.org/
 D: obmouse - rewrote Olivier Florent's Omnibook 600 "pop-up" mouse driver
@@ -2492,7 +2491,7 @@ S: Syracuse, New York 13206
 S: USA
 
 N: Kyle McMartin
-E: kyle@parisc-linux.org
+E: kyle@mcmartin.ca
 D: Linux/PARISC hacker
 D: AD1889 sound driver
 S: Ottawa, Canada
@@ -3780,14 +3779,13 @@ S: 21513 Conradia Ct
 S: Cupertino, CA 95014
 S: USA
 
-N: Thibaut Varene
-E: T-Bone@parisc-linux.org
-W: http://www.parisc-linux.org/~varenet/
-P: 1024D/B7D2F063 E67C 0D43 A75E 12A5 BB1C  FA2F 1E32 C3DA B7D2 F063
+N: Thibaut Varène
+E: hacks+kernel@slashdirt.org
+W: http://hacks.slashdirt.org/
 D: PA-RISC port minion, PDC and GSCPS2 drivers, debuglocks and other bits
 D: Some ARM at91rm9200 bits, S1D13XXX FB driver, random patches here and there
 D: AD1889 sound driver
-S: Paris, France
+S: France
 
 N: Heikki Vatiainen
 E: hessu@cs.tut.fi
index 9b64266..169fe08 100644 (file)
@@ -24,7 +24,7 @@ What:         /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
                                                        cpld3_version
 
 Date:          November 2018
-KernelVersion: 4.21
+KernelVersion: 5.0
 Contact:       Vadim Pasternak <vadimpmellanox.com>
 Description:   These files show with which CPLD versions have been burned
                on LED board.
@@ -35,7 +35,7 @@ What:         /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
                                                        jtag_enable
 
 Date:          November 2018
-KernelVersion: 4.21
+KernelVersion: 5.0
 Contact:       Vadim Pasternak <vadimpmellanox.com>
 Description:   These files enable and disable the access to the JTAG domain.
                By default access to the JTAG domain is disabled.
@@ -105,7 +105,7 @@ What:               /sys/devices/platform/mlxplat/mlxreg-io/hwmon/hwmon*/
                                                reset_voltmon_upgrade_fail
 
 Date:          November 2018
-KernelVersion: 4.21
+KernelVersion: 5.0
 Contact:       Vadim Pasternak <vadimpmellanox.com>
 Description:   These files show the system reset cause, as following: ComEx
                power fail, reset from ComEx, system platform reset, reset
index 7710d40..dfad742 100644 (file)
@@ -279,3 +279,12 @@ Description:
                size in 512B sectors of the zones of the device, with
                the eventual exception of the last zone of the device
                which may be smaller.
+
+What:          /sys/block/<disk>/queue/io_timeout
+Date:          November 2018
+Contact:       Weiping Zhang <zhangweiping@didiglobal.com>
+Description:
+               io_timeout is the request timeout in milliseconds. If a request
+               does not complete in this time then the block driver timeout
+               handler is invoked. That timeout handler can decide to retry
+               the request, to fail it or to start a device recovery strategy.
index 9d2339a..14b2bf2 100644 (file)
@@ -122,11 +122,18 @@ Description:
                statistics (bd_count, bd_reads, bd_writes) in a format
                similar to block layer statistics file format.
 
+What:          /sys/block/zram<id>/writeback_limit_enable
+Date:          November 2018
+Contact:       Minchan Kim <minchan@kernel.org>
+Description:
+               The writeback_limit_enable file is read-write and specifies
+               eanbe of writeback_limit feature. "1" means eable the feature.
+               No limit "0" is the initial state.
+
 What:          /sys/block/zram<id>/writeback_limit
 Date:          November 2018
 Contact:       Minchan Kim <minchan@kernel.org>
 Description:
                The writeback_limit file is read-write and specifies the maximum
                amount of writeback ZRAM can do. The limit could be changed
-               in run time and "0" means disable the limit.
-               No limit is the initial state.
+               in run time.
index 0797eec..47e5772 100644 (file)
@@ -1,9 +1,9 @@
 .. _readme:
 
-Linux kernel release 4.x <http://kernel.org/>
+Linux kernel release 5.x <http://kernel.org/>
 =============================================
 
-These are the release notes for Linux version 4.  Read them carefully,
+These are the release notes for Linux version 5.  Read them carefully,
 as they tell you what this is all about, explain how to install the
 kernel, and what to do if something goes wrong.
 
@@ -63,7 +63,7 @@ Installing the kernel source
    directory where you have permissions (e.g. your home directory) and
    unpack it::
 
-     xz -cd linux-4.X.tar.xz | tar xvf -
+     xz -cd linux-5.x.tar.xz | tar xvf -
 
    Replace "X" with the version number of the latest kernel.
 
@@ -72,26 +72,26 @@ Installing the kernel source
    files.  They should match the library, and not get messed up by
    whatever the kernel-du-jour happens to be.
 
- - You can also upgrade between 4.x releases by patching.  Patches are
+ - You can also upgrade between 5.x releases by patching.  Patches are
    distributed in the xz format.  To install by patching, get all the
    newer patch files, enter the top level directory of the kernel source
-   (linux-4.X) and execute::
+   (linux-5.x) and execute::
 
-     xz -cd ../patch-4.x.xz | patch -p1
+     xz -cd ../patch-5.x.xz | patch -p1
 
-   Replace "x" for all versions bigger than the version "X" of your current
+   Replace "x" for all versions bigger than the version "x" of your current
    source tree, **in_order**, and you should be ok.  You may want to remove
    the backup files (some-file-name~ or some-file-name.orig), and make sure
    that there are no failed patches (some-file-name# or some-file-name.rej).
    If there are, either you or I have made a mistake.
 
-   Unlike patches for the 4.x kernels, patches for the 4.x.y kernels
+   Unlike patches for the 5.x kernels, patches for the 5.x.y kernels
    (also known as the -stable kernels) are not incremental but instead apply
-   directly to the base 4.x kernel.  For example, if your base kernel is 4.0
-   and you want to apply the 4.0.3 patch, you must not first apply the 4.0.1
-   and 4.0.2 patches. Similarly, if you are running kernel version 4.0.2 and
-   want to jump to 4.0.3, you must first reverse the 4.0.2 patch (that is,
-   patch -R) **before** applying the 4.0.3 patch. You can read more on this in
+   directly to the base 5.x kernel.  For example, if your base kernel is 5.0
+   and you want to apply the 5.0.3 patch, you must not first apply the 5.0.1
+   and 5.0.2 patches. Similarly, if you are running kernel version 5.0.2 and
+   want to jump to 5.0.3, you must first reverse the 5.0.2 patch (that is,
+   patch -R) **before** applying the 5.0.3 patch. You can read more on this in
    :ref:`Documentation/process/applying-patches.rst <applying_patches>`.
 
    Alternatively, the script patch-kernel can be used to automate this
@@ -114,7 +114,7 @@ Installing the kernel source
 Software requirements
 ---------------------
 
-   Compiling and running the 4.x kernels requires up-to-date
+   Compiling and running the 5.x kernels requires up-to-date
    versions of various software packages.  Consult
    :ref:`Documentation/process/changes.rst <changes>` for the minimum version numbers
    required and how to get updates for these packages.  Beware that using
@@ -132,12 +132,12 @@ Build directory for the kernel
    place for the output files (including .config).
    Example::
 
-     kernel source code: /usr/src/linux-4.X
+     kernel source code: /usr/src/linux-5.x
      build directory:    /home/name/build/kernel
 
    To configure and build the kernel, use::
 
-     cd /usr/src/linux-4.X
+     cd /usr/src/linux-5.x
      make O=/home/name/build/kernel menuconfig
      make O=/home/name/build/kernel
      sudo make O=/home/name/build/kernel modules_install install
index b799bcf..858b6c0 100644 (file)
                        By default, super page will be supported if Intel IOMMU
                        has the capability. With this option, super page will
                        not be supported.
-               sm_off [Default Off]
-                       By default, scalable mode will be supported if the
+               sm_on [Default Off]
+                       By default, scalable mode will be disabled even if the
                        hardware advertises that it has support for the scalable
                        mode translation. With this option set, scalable mode
-                       will not be used even on hardware which claims to support
-                       it.
+                       will be used on hardware which claims to support it.
                tboot_noforce [Default Off]
                        Do not force the Intel IOMMU enabled under tboot.
                        By default, tboot will force Intel IOMMU on, which
index 8d8d8f0..98a8dd5 100644 (file)
@@ -357,6 +357,13 @@ video playing/streaming, a very low drop rate may be more important
 than maximum throughput. In these cases, consider setting the
 strict_guarantees parameter.
 
+slice_idle_us
+-------------
+
+Controls the same tuning parameter as slice_idle, but in microseconds.
+Either tunable can be used to set idling behavior.  Afterwards, the
+other tunable will reflect the newly set value in sysfs.
+
 strict_guarantees
 -----------------
 
index ea2dafe..4cad102 100644 (file)
@@ -88,7 +88,8 @@ shared_tags=[0/1]: Default: 0
 
 zoned=[0/1]: Default: 0
   0: Block device is exposed as a random-access block device.
-  1: Block device is exposed as a host-managed zoned block device.
+  1: Block device is exposed as a host-managed zoned block device. Requires
+     CONFIG_BLK_DEV_ZONED.
 
 zone_size=[MB]: Default: 256
   Per zone size when exposed as a zoned block device. Must be a power of two.
index 39e286d..83b457e 100644 (file)
@@ -67,6 +67,13 @@ If set to a value larger than 0, the kernel will put the process issuing
 IO to sleep for this amount of microseconds before entering classic
 polling.
 
+io_timeout (RW)
+---------------
+io_timeout is the request timeout in milliseconds. If a request does not
+complete in this time then the block driver timeout handler is invoked.
+That timeout handler can decide to retry the request, to fail it or to start
+a device recovery strategy.
+
 iostats (RW)
 -------------
 This file is used to control (on/off) the iostats accounting of the
index 436c5e9..4df0ce2 100644 (file)
@@ -156,22 +156,23 @@ Per-device statistics are exported as various nodes under /sys/block/zram<id>/
 A brief description of exported device attributes. For more details please
 read Documentation/ABI/testing/sysfs-block-zram.
 
-Name            access            description
-----            ------            -----------
-disksize          RW    show and set the device's disk size
-initstate         RO    shows the initialization state of the device
-reset             WO    trigger device reset
-mem_used_max      WO    reset the `mem_used_max' counter (see later)
-mem_limit         WO    specifies the maximum amount of memory ZRAM can use
-                        to store the compressed data
-writeback_limit   WO    specifies the maximum amount of write IO zram can
-                       write out to backing device as 4KB unit
-max_comp_streams  RW    the number of possible concurrent compress operations
-comp_algorithm    RW    show and change the compression algorithm
-compact           WO    trigger memory compaction
-debug_stat        RO    this file is used for zram debugging purposes
-backing_dev      RW    set up backend storage for zram to write out
-idle             WO    mark allocated slot as idle
+Name                   access            description
+----                   ------            -----------
+disksize               RW      show and set the device's disk size
+initstate              RO      shows the initialization state of the device
+reset                  WO      trigger device reset
+mem_used_max           WO      reset the `mem_used_max' counter (see later)
+mem_limit              WO      specifies the maximum amount of memory ZRAM can use
+                               to store the compressed data
+writeback_limit        WO      specifies the maximum amount of write IO zram can
+                               write out to backing device as 4KB unit
+writeback_limit_enable  RW     show and set writeback_limit feature
+max_comp_streams       RW      the number of possible concurrent compress operations
+comp_algorithm         RW      show and change the compression algorithm
+compact                WO      trigger memory compaction
+debug_stat             RO      this file is used for zram debugging purposes
+backing_dev            RW      set up backend storage for zram to write out
+idle                   WO      mark allocated slot as idle
 
 
 User space is advised to use the following files to read the device statistics.
@@ -280,32 +281,51 @@ With the command, zram writeback idle pages from memory to the storage.
 If there are lots of write IO with flash device, potentially, it has
 flash wearout problem so that admin needs to design write limitation
 to guarantee storage health for entire product life.
-To overcome the concern, zram supports "writeback_limit".
-The "writeback_limit"'s default value is 0 so that it doesn't limit
-any writeback. If admin want to measure writeback count in a certain
-period, he could know it via /sys/block/zram0/bd_stat's 3rd column.
+
+To overcome the concern, zram supports "writeback_limit" feature.
+The "writeback_limit_enable"'s default value is 0 so that it doesn't limit
+any writeback. IOW, if admin want to apply writeback budget, he should
+enable writeback_limit_enable via
+
+       $ echo 1 > /sys/block/zramX/writeback_limit_enable
+
+Once writeback_limit_enable is set, zram doesn't allow any writeback
+until admin set the budget via /sys/block/zramX/writeback_limit.
+
+(If admin doesn't enable writeback_limit_enable, writeback_limit's value
+assigned via /sys/block/zramX/writeback_limit is meaninless.)
 
 If admin want to limit writeback as per-day 400M, he could do it
 like below.
 
-    MB_SHIFT=20
-    4K_SHIFT=12
-    echo $((400<<MB_SHIFT>>4K_SHIFT)) > \
-           /sys/block/zram0/writeback_limit.
+       $ MB_SHIFT=20
+       $ 4K_SHIFT=12
+       $ echo $((400<<MB_SHIFT>>4K_SHIFT)) > \
+               /sys/block/zram0/writeback_limit.
+       $ echo 1 > /sys/block/zram0/writeback_limit_enable
 
-If admin want to allow further write again, he could do it like below
+If admin want to allow further write again once the bugdet is exausted,
+he could do it like below
 
-    echo 0 > /sys/block/zram0/writeback_limit
+       $ echo $((400<<MB_SHIFT>>4K_SHIFT)) > \
+               /sys/block/zram0/writeback_limit
 
 If admin want to see remaining writeback budget since he set,
 
-    cat /sys/block/zram0/writeback_limit
+       $ cat /sys/block/zramX/writeback_limit
+
+If admin want to disable writeback limit, he could do
+
+       $ echo 0 > /sys/block/zramX/writeback_limit_enable
 
 The writeback_limit count will reset whenever you reset zram(e.g.,
 system reboot, echo 1 > /sys/block/zramX/reset) so keeping how many of
 writeback happened until you reset the zram to allocate extra writeback
 budget in next setting is user's job.
 
+If admin want to measure writeback count in a certain period, he could
+know it via /sys/block/zram0/bd_stat's 3rd column.
+
 = memory tracking
 
 With CONFIG_ZRAM_MEMORY_TRACKING, user can know information of the
index 6780a6d..7cc9e36 100644 (file)
@@ -157,12 +157,11 @@ Q: Does BPF have a stable ABI?
 ------------------------------
 A: YES. BPF instructions, arguments to BPF programs, set of helper
 functions and their arguments, recognized return codes are all part
-of ABI. However when tracing programs are using bpf_probe_read() helper
-to walk kernel internal datastructures and compile with kernel
-internal headers these accesses can and will break with newer
-kernels. The union bpf_attr -> kern_version is checked at load time
-to prevent accidentally loading kprobe-based bpf programs written
-for a different kernel. Networking programs don't do kern_version check.
+of ABI. However there is one specific exception to tracing programs
+which are using helpers like bpf_probe_read() to walk kernel internal
+data structures and compile with kernel internal headers. Both of these
+kernel internals are subject to change and can break with newer kernels
+such that the program needs to be adapted accordingly.
 
 Q: How much stack space a BPF program uses?
 -------------------------------------------
index 6a6d67a..5d54b27 100644 (file)
@@ -108,12 +108,13 @@ some, but not all of the other indices changing.
 
 Sometimes you need to ensure that a subsequent call to :c:func:`xa_store`
 will not need to allocate memory.  The :c:func:`xa_reserve` function
-will store a reserved entry at the indicated index.  Users of the normal
-API will see this entry as containing ``NULL``.  If you do not need to
-use the reserved entry, you can call :c:func:`xa_release` to remove the
-unused entry.  If another user has stored to the entry in the meantime,
-:c:func:`xa_release` will do nothing; if instead you want the entry to
-become ``NULL``, you should use :c:func:`xa_erase`.
+will store a reserved entry at the indicated index.  Users of the
+normal API will see this entry as containing ``NULL``.  If you do
+not need to use the reserved entry, you can call :c:func:`xa_release`
+to remove the unused entry.  If another user has stored to the entry
+in the meantime, :c:func:`xa_release` will do nothing; if instead you
+want the entry to become ``NULL``, you should use :c:func:`xa_erase`.
+Using :c:func:`xa_insert` on a reserved entry will fail.
 
 If all entries in the array are ``NULL``, the :c:func:`xa_empty` function
 will return ``true``.
@@ -183,6 +184,8 @@ Takes xa_lock internally:
  * :c:func:`xa_store_bh`
  * :c:func:`xa_store_irq`
  * :c:func:`xa_insert`
+ * :c:func:`xa_insert_bh`
+ * :c:func:`xa_insert_irq`
  * :c:func:`xa_erase`
  * :c:func:`xa_erase_bh`
  * :c:func:`xa_erase_irq`
index 6e5cef0..50daa0b 100644 (file)
@@ -17,7 +17,11 @@ extra-y += $(DT_TMP_SCHEMA)
 quiet_cmd_mk_schema = SCHEMA  $@
       cmd_mk_schema = $(DT_MK_SCHEMA) $(DT_MK_SCHEMA_FLAGS) -o $@ $(filter-out FORCE, $^)
 
-DT_DOCS = $(shell cd $(srctree)/$(src) && find * -name '*.yaml')
+DT_DOCS = $(shell \
+       cd $(srctree)/$(src) && \
+       find * \( -name '*.yaml' ! -name $(DT_TMP_SCHEMA) \) \
+       )
+
 DT_SCHEMA_FILES ?= $(addprefix $(src)/,$(DT_DOCS))
 
 extra-y += $(patsubst $(src)/%.yaml,%.example.dts, $(DT_SCHEMA_FILES))
index 84262cd..96fa46c 100644 (file)
@@ -235,4 +235,4 @@ cpus {
 ===========================================
 
 [1] ARM Linux Kernel documentation - CPUs bindings
-    Documentation/devicetree/bindings/arm/cpus.txt
+    Documentation/devicetree/bindings/arm/cpus.yaml
index 8f0937d..45730ba 100644 (file)
@@ -684,7 +684,7 @@ cpus {
 ===========================================
 
 [1] ARM Linux Kernel documentation - CPUs bindings
-    Documentation/devicetree/bindings/arm/cpus.txt
+    Documentation/devicetree/bindings/arm/cpus.yaml
 
 [2] ARM Linux Kernel documentation - PSCI bindings
     Documentation/devicetree/bindings/arm/psci.txt
index 1b2ab1f..46652bf 100644 (file)
@@ -4,7 +4,7 @@ SP810 System Controller
 Required properties:
 
 - compatible:  standard compatible string for a Primecell peripheral,
-               see Documentation/devicetree/bindings/arm/primecell.txt
+               see Documentation/devicetree/bindings/arm/primecell.yaml
                for more details
                should be: "arm,sp810", "arm,primecell"
 
index de9eb04..b0d80c0 100644 (file)
@@ -472,4 +472,4 @@ cpus {
 
 ===============================================================================
 [1] ARM Linux kernel documentation
-    Documentation/devicetree/bindings/arm/cpus.txt
+    Documentation/devicetree/bindings/arm/cpus.yaml
index 2ef86ae..d19885b 100644 (file)
@@ -2,13 +2,14 @@
 
 The Actions Semi Owl Clock Management Unit generates and supplies clock
 to various controllers within the SoC. The clock binding described here is
-applicable to S900 and S700 SoC's.
+applicable to S900, S700 and S500 SoC's.
 
 Required Properties:
 
 - compatible: should be one of the following,
        "actions,s900-cmu"
        "actions,s700-cmu"
+       "actions,s500-cmu"
 - reg: physical base address of the controller and length of memory mapped
   region.
 - clocks: Reference to the parent clocks ("hosc", "losc")
@@ -19,8 +20,8 @@ Each clock is assigned an identifier, and client nodes can use this identifier
 to specify the clock which they consume.
 
 All available clocks are defined as preprocessor macros in corresponding
-dt-bindings/clock/actions,s900-cmu.h or actions,s700-cmu.h header and can be
-used in device tree sources.
+dt-bindings/clock/actions,s900-cmu.h or actions,s700-cmu.h or
+actions,s500-cmu.h header and can be used in device tree sources.
 
 External clocks:
 
index 79511d7..c41f0be 100644 (file)
@@ -10,6 +10,7 @@ Required Properties:
        - GXL (S905X, S905D) : "amlogic,meson-gxl-aoclkc"
        - GXM (S912) : "amlogic,meson-gxm-aoclkc"
        - AXG (A113D, A113X) : "amlogic,meson-axg-aoclkc"
+       - G12A (S905X2, S905D2, S905Y2) : "amlogic,meson-g12a-aoclkc"
        followed by the common "amlogic,meson-gx-aoclkc"
 - clocks: list of clock phandle, one for each entry clock-names.
 - clock-names: should contain the following:
index a687195..5c8b105 100644 (file)
@@ -9,6 +9,7 @@ Required Properties:
                "amlogic,gxbb-clkc" for GXBB SoC,
                "amlogic,gxl-clkc" for GXL and GXM SoC,
                "amlogic,axg-clkc" for AXG SoC.
+               "amlogic,g12a-clkc" for G12A SoC.
 - clocks : list of clock phandle, one for each entry clock-names.
 - clock-names : should contain the following:
   * "xtal": the platform xtal
index 50d5897..183c327 100644 (file)
@@ -50,6 +50,8 @@ Required Properties:
     IPs.
   - "samsung,exynos5433-cmu-cam1" - clock controller compatible for CMU_CAM1
     which generates clocks for Cortex-A5/MIPI_CSIS2/FIMC-LITE_C/FIMC-FD IPs.
+  - "samsung,exynos5433-cmu-imem"   - clock controller compatible for CMU_IMEM
+    which generates clocks for SSS (Security SubSystem) and SlimSSS IPs.
 
 - reg: physical base address of the controller and length of memory mapped
   region.
@@ -168,6 +170,12 @@ Required Properties:
                - aclk_cam1_400
                - aclk_cam1_552
 
+       Input clocks for imem clock controller:
+               - oscclk
+               - aclk_imem_sssx_266
+               - aclk_imem_266
+               - aclk_imem_200
+
 Optional properties:
   - power-domains: a phandle to respective power domain node as described by
        generic PM domain bindings (see power/power_domain.txt for more
@@ -469,6 +477,21 @@ Example 2: Examples of clock controller nodes are listed below.
                power-domains = <&pd_cam1>;
        };
 
+       cmu_imem: clock-controller@11060000 {
+               compatible = "samsung,exynos5433-cmu-imem";
+               reg = <0x11060000 0x1000>;
+               #clock-cells = <1>;
+
+               clock-names = "oscclk",
+                       "aclk_imem_sssx_266",
+                       "aclk_imem_266",
+                       "aclk_imem_200";
+               clocks = <&xxti>,
+                       <&cmu_top CLK_DIV_ACLK_IMEM_SSSX_266>,
+                       <&cmu_top CLK_DIV_ACLK_IMEM_266>,
+                       <&cmu_top CLK_DIV_ACLK_IMEM_200>;
+       };
+
 Example 3: UART controller node that consumes the clock generated by the clock
           controller.
 
diff --git a/Documentation/devicetree/bindings/clock/fixed-mmio-clock.txt b/Documentation/devicetree/bindings/clock/fixed-mmio-clock.txt
new file mode 100644 (file)
index 0000000..c359367
--- /dev/null
@@ -0,0 +1,24 @@
+Binding for simple memory mapped io fixed-rate clock sources.
+The driver reads a clock frequency value from a single 32-bit memory mapped
+I/O register and registers it as a fixed rate clock.
+
+It was designed for test systems, like FPGA, not for complete, finished SoCs.
+
+This binding uses the common clock binding[1].
+
+[1] Documentation/devicetree/bindings/clock/clock-bindings.txt
+
+Required properties:
+- compatible : shall be "fixed-mmio-clock".
+- #clock-cells : from common clock binding; shall be set to 0.
+- reg : Address and length of the clock value register set.
+
+Optional properties:
+- clock-output-names : From common clock binding.
+
+Example:
+sysclock: sysclock@fd020004 {
+       #clock-cells = <0>;
+       compatible = "fixed-mmio-clock";
+       reg = <0xfd020004 0x4>;
+};
diff --git a/Documentation/devicetree/bindings/clock/imx8mm-clock.txt b/Documentation/devicetree/bindings/clock/imx8mm-clock.txt
new file mode 100644 (file)
index 0000000..8e4ab9e
--- /dev/null
@@ -0,0 +1,29 @@
+* Clock bindings for NXP i.MX8M Mini
+
+Required properties:
+- compatible: Should be "fsl,imx8mm-ccm"
+- reg: Address and length of the register set
+- #clock-cells: Should be <1>
+- clocks: list of clock specifiers, must contain an entry for each required
+          entry in clock-names
+- clock-names: should include the following entries:
+    - "osc_32k"
+    - "osc_24m"
+    - "clk_ext1"
+    - "clk_ext2"
+    - "clk_ext3"
+    - "clk_ext4"
+
+clk: clock-controller@30380000 {
+       compatible = "fsl,imx8mm-ccm";
+       reg = <0x0 0x30380000 0x0 0x10000>;
+       #clock-cells = <1>;
+       clocks = <&osc_32k>, <&osc_24m>, <&clk_ext1>, <&clk_ext2>,
+                <&clk_ext3>, <&clk_ext4>;
+       clock-names = "osc_32k", "osc_24m", "clk_ext1", "clk_ext2",
+                     "clk_ext3", "clk_ext4";
+};
+
+The clock consumer should specify the desired clock by having the clock
+ID in its "clocks" phandle cell. See include/dt-bindings/clock/imx8mm-clock.h
+for the full list of i.MX8M Mini clock IDs.
index af376a0..23b52dc 100644 (file)
@@ -18,4 +18,4 @@ Required Properties:
 Each clock is assigned an identifier and client nodes use this identifier
 to specify the clock which they consume.
 
-All these identifier could be found in <dt-bindings/clock/marvell-mmp2.h>.
+All these identifiers could be found in <dt-bindings/clock/marvell,mmp2.h>.
index 87b4949..944719b 100644 (file)
@@ -16,6 +16,7 @@ Required properties :
                        "qcom,rpmcc-msm8974", "qcom,rpmcc"
                        "qcom,rpmcc-apq8064", "qcom,rpmcc"
                        "qcom,rpmcc-msm8996", "qcom,rpmcc"
+                       "qcom,rpmcc-msm8998", "qcom,rpmcc"
                        "qcom,rpmcc-qcs404", "qcom,rpmcc"
 
 - #clock-cells : shall contain 1
index ef89ab4..572fa27 100644 (file)
@@ -1,6 +1,6 @@
 * ARM PrimeCell Color LCD Controller PL110/PL111
 
-See also Documentation/devicetree/bindings/arm/primecell.txt
+See also Documentation/devicetree/bindings/arm/primecell.yaml
 
 Required properties:
 
index ac8df3b..f875914 100644 (file)
@@ -27,7 +27,6 @@ Example:
                reg = <0x04300000 0x20000>;
                reg-names = "kgsl_3d0_reg_memory";
                interrupts = <GIC_SPI 80 0>;
-               interrupt-names = "kgsl_3d0_irq";
                clock-names =
                    "core",
                    "iface",
index 38ca220..2e097b5 100644 (file)
@@ -14,8 +14,6 @@ Required properties:
 
     "marvell,armada-8k-gpio" should be used for the Armada 7K and 8K
     SoCs (either from AP or CP), see
-    Documentation/devicetree/bindings/arm/marvell/cp110-system-controller0.txt
-    and
     Documentation/devicetree/bindings/arm/marvell/ap806-system-controller.txt
     for specific details about the offset property.
 
index b83bb82..a3be529 100644 (file)
@@ -78,7 +78,7 @@ Sub-nodes:
 PPI affinity can be expressed as a single "ppi-partitions" node,
 containing a set of sub-nodes, each with the following property:
 - affinity: Should be a list of phandles to CPU nodes (as described in
-Documentation/devicetree/bindings/arm/cpus.txt).
+  Documentation/devicetree/bindings/arm/cpus.yaml).
 
 GICv3 has one or more Interrupt Translation Services (ITS) that are
 used to route Message Signalled Interrupts (MSI) to the CPUs.
index 98c9f56..38fe34f 100644 (file)
@@ -1,7 +1,8 @@
 Altera SOCFPGA Reset Manager
 
 Required properties:
-- compatible : "altr,rst-mgr"
+- compatible : "altr,rst-mgr" for (Cyclone5/Arria5/Arria10)
+              "altr,stratix10-rst-mgr","altr,rst-mgr" for Stratix10 ARM64 SoC
 - reg : Should contain 1 register ranges(address and length)
 - altr,modrst-offset : Should contain the offset of the first modrst register.
 - #reset-cells: 1
index 101743d..ea00517 100644 (file)
@@ -120,27 +120,30 @@ Example:
        };
 
 
-USB3 core reset
----------------
+Peripheral core reset in glue layer
+-----------------------------------
 
-USB3 core reset belongs to USB3 glue layer. Before using the core reset,
-it is necessary to control the clocks and resets to enable this layer.
-These clocks and resets should be described in each property.
+Some peripheral core reset belongs to its own glue layer. Before using
+this core reset, it is necessary to control the clocks and resets to enable
+this layer. These clocks and resets should be described in each property.
 
 Required properties:
 - compatible: Should be
-    "socionext,uniphier-pro4-usb3-reset" - for Pro4 SoC
-    "socionext,uniphier-pxs2-usb3-reset" - for PXs2 SoC
-    "socionext,uniphier-ld20-usb3-reset" - for LD20 SoC
-    "socionext,uniphier-pxs3-usb3-reset" - for PXs3 SoC
+    "socionext,uniphier-pro4-usb3-reset" - for Pro4 SoC USB3
+    "socionext,uniphier-pxs2-usb3-reset" - for PXs2 SoC USB3
+    "socionext,uniphier-ld20-usb3-reset" - for LD20 SoC USB3
+    "socionext,uniphier-pxs3-usb3-reset" - for PXs3 SoC USB3
+    "socionext,uniphier-pro4-ahci-reset" - for Pro4 SoC AHCI
+    "socionext,uniphier-pxs2-ahci-reset" - for PXs2 SoC AHCI
+    "socionext,uniphier-pxs3-ahci-reset" - for PXs3 SoC AHCI
 - #reset-cells: Should be 1.
 - reg: Specifies offset and length of the register set for the device.
-- clocks: A list of phandles to the clock gate for USB3 glue layer.
+- clocks: A list of phandles to the clock gate for the glue layer.
        According to the clock-names, appropriate clocks are required.
 - clock-names: Should contain
     "gio", "link" - for Pro4 SoC
     "link"        - for others
-- resets: A list of phandles to the reset control for USB3 glue layer.
+- resets: A list of phandles to the reset control for the glue layer.
        According to the reset-names, appropriate resets are required.
 - reset-names: Should contain
     "gio", "link" - for Pro4 SoC
index 3660341..0e72183 100644 (file)
@@ -4,14 +4,10 @@ Required properties:
 - compatible : "olpc,ap-sp"
 - reg : base address and length of SoC's WTM registers
 - interrupts : SP-AP interrupt
-- clocks : phandle + clock-specifier for the clock that drives the WTM
-- clock-names:  should be "sp"
 
 Example:
        ap-sp@d4290000 {
                compatible = "olpc,ap-sp";
                reg = <0xd4290000 0x1000>;
                interrupts = <40>;
-               clocks = <&soc_clocks MMP2_CLK_SP>;
-               clock-names = "sp";
        }
index 0b8cc53..cf759e5 100644 (file)
@@ -55,7 +55,7 @@ of these nodes are defined by the individual bindings for the specific function
 = EXAMPLE
 The following example represents the GLINK RPM node on a MSM8996 device, with
 the function for the "rpm_request" channel defined, which is used for
-regualtors and root clocks.
+regulators and root clocks.
 
        apcs_glb: mailbox@9820000 {
                compatible = "qcom,msm8996-apcs-hmss-global";
index a35af2d..49e1d72 100644 (file)
@@ -41,12 +41,12 @@ processor ID) and a string identifier.
 - qcom,local-pid:
        Usage: required
        Value type: <u32>
-       Definition: specifies the identfier of the local endpoint of this edge
+       Definition: specifies the identifier of the local endpoint of this edge
 
 - qcom,remote-pid:
        Usage: required
        Value type: <u32>
-       Definition: specifies the identfier of the remote endpoint of this edge
+       Definition: specifies the identifier of the remote endpoint of this edge
 
 = SUBNODES
 Each SMP2P pair contain a set of inbound and outbound entries, these are
index b577a45..c247b48 100644 (file)
@@ -124,11 +124,11 @@ struct bus_attribute {
        ssize_t (*store)(struct bus_type *, const char * buf, size_t count);
 };
 
-Bus drivers can export attributes using the BUS_ATTR macro that works
-similarly to the DEVICE_ATTR macro for devices. For example, a definition 
-like this:
+Bus drivers can export attributes using the BUS_ATTR_RW macro that works
+similarly to the DEVICE_ATTR_RW macro for devices. For example, a
+definition like this:
 
-static BUS_ATTR(debug,0644,show_debug,store_debug);
+static BUS_ATTR_RW(debug);
 
 is equivalent to declaring:
 
index b277caf..d7d6f01 100644 (file)
@@ -242,9 +242,11 @@ certainly invest a bit more effort into libata core layer).
 
 CLOCK
   devm_clk_get()
+  devm_clk_get_optional()
   devm_clk_put()
   devm_clk_hw_register()
   devm_of_clk_add_hw_provider()
+  devm_clk_hw_register_clkdev()
 
 DMA
   dmaenginem_async_device_register()
index 62af305..60a5ec0 100644 (file)
@@ -163,6 +163,14 @@ C. Boot options
        be preserved until there actually is some text is output to the console.
        This option causes fbcon to bind immediately to the fbdev device.
 
+7. fbcon=logo-pos:<location>
+
+       The only possible 'location' is 'center' (without quotes), and when
+       given, the bootup logo is moved from the default top-left corner
+       location to the center of the framebuffer. If more than one logo is
+       displayed due to multiple CPUs, the collected line of logos is moved
+       as a whole.
+
 C. Attaching, Detaching and Unloading
 
 Before going on to how to attach, detach and unload the framebuffer console, an
index 90459cd..8620c38 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: | TODO |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index c90a038..9ae6e8d 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 0ef6acd..365df2c 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: |  ok  |
     |       h8300: | TODO |
     |     hexagon: |  ok  |
     |        ia64: |  ok  |
index 6011139..7fc2e24 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index f44c274..d344b99 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: |  ok  |
+    |        csky: |  ok  |
     |       h8300: | TODO |
     |     hexagon: |  ok  |
     |        ia64: |  ok  |
index 282ecc8..304dcd4 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 01b2b30..059d58a 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 3b4dff2..3e6b8f0 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: |  ok  |
     |     hexagon: |  ok  |
     |        ia64: | TODO |
index 7e963d0..68f2669 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: | TODO |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 4ada027..f4e45bd 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: |  ok  |
index 044e13f..1d5651e 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: |  ok  |
index dce7669..fb297a8 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: | TODO |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 954ac1c..9999ea5 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 1a3f9d3..1c577d0 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 1d78d10..6bfa36b 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: | TODO |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 30c072d..eb28b5c 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: |  ok  |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 51704a2..242ff5a 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index bd39c5e..941fd5b 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: |  ok  |
     |        ia64: | TODO |
index da7aff3..c683da1 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: |  ok  |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 478e910..e3080b8 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: | TODO |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index e54b1f1..7521d75 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: |  ok  |
index 7331402..d8278bf 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: |  ok  |
     |        ia64: | TODO |
index 53feeee..687d049 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 1616434..90996e3 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index c7858dd..8a521a6 100644 (file)
@@ -34,6 +34,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index c68bb2c..3508236 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ..  |
     |       arm64: |  ok  |
     |         c6x: |  ..  |
+    |        csky: |  ..  |
     |       h8300: |  ..  |
     |     hexagon: |  ..  |
     |        ia64: | TODO |
index d4271b4..4fe6c3c 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 83d9e68..593536f 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 3d4908f..7a27157 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: |  ok  |
+    |        csky: |  ok  |
     |       h8300: |  ok  |
     |     hexagon: |  ok  |
     |        ia64: | TODO |
index c29974a..048bfb6 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 8d73c46..a14bbad 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: |  ..  |
index e7c6ea6..2855dfe 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: |  ok  |
     |         c6x: |  ok  |
+    |        csky: |  ok  |
     |       h8300: |  ok  |
     |     hexagon: |  ok  |
     |        ia64: |  ok  |
index 4646457..fb0d0ca 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: |  ok  |
index 1f71d09..adc2587 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index fbd5aa4..f05588f 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: | TODO |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: |  ok  |
index 5d7ecc3..cdfe892 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: |  ..  |
+    |        csky: |  ..  |
     |       h8300: |  ..  |
     |     hexagon: |  ..  |
     |        ia64: | TODO |
index f7af967..2bdd3b6 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: | TODO |
     |         c6x: |  ..  |
+    |        csky: | TODO |
     |       h8300: |  ..  |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index d0713cc..019131c 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 326e479..3a6b87d 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: | TODO |
     |       arm64: | TODO |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index 1a98805..3004beb 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ..  |
     |       arm64: |  ok  |
     |         c6x: |  ..  |
+    |        csky: |  ..  |
     |       h8300: |  ..  |
     |     hexagon: |  ..  |
     |        ia64: |  ok  |
index a837842..2dc5df6 100644 (file)
@@ -11,6 +11,7 @@
     |         arm: |  ok  |
     |       arm64: |  ok  |
     |         c6x: | TODO |
+    |        csky: | TODO |
     |       h8300: | TODO |
     |     hexagon: | TODO |
     |        ia64: | TODO |
index a1426ca..41411b0 100644 (file)
@@ -344,7 +344,9 @@ struct bus_attribute {
 
 Declaring:
 
-BUS_ATTR(_name, _mode, _show, _store)
+static BUS_ATTR_RW(name);
+static BUS_ATTR_RO(name);
+static BUS_ATTR_WO(name);
 
 Creation/Removal:
 
index 25170ad..101f2b2 100644 (file)
@@ -533,16 +533,12 @@ Bridge VLAN filtering
   function that the driver has to call for each VLAN the given port is a member
   of. A switchdev object is used to carry the VID and bridge flags.
 
-- port_fdb_prepare: bridge layer function invoked when the bridge prepares the
-  installation of a Forwarding Database entry. If the operation is not
-  supported, this function should return -EOPNOTSUPP to inform the bridge code
-  to fallback to a software implementation. No hardware setup must be done in
-  this function. See port_fdb_add for this and details.
-
 - port_fdb_add: bridge layer function invoked when the bridge wants to install a
   Forwarding Database entry, the switch hardware should be programmed with the
   specified address in the specified VLAN Id in the forwarding database
-  associated with this VLAN ID
+  associated with this VLAN ID. If the operation is not supported, this
+  function should return -EOPNOTSUPP to inform the bridge code to fallback to
+  a software implementation.
 
 Note: VLAN ID 0 corresponds to the port private database, which, in the context
 of DSA, would be the its port-based VLAN, used by the associated bridge device.
index 6a47629..59e86de 100644 (file)
@@ -11,19 +11,19 @@ Contents:
    batman-adv
    can
    can_ucan_protocol
-   dpaa2/index
-   e100
-   e1000
-   e1000e
-   fm10k
-   igb
-   igbvf
-   ixgb
-   ixgbe
-   ixgbevf
-   i40e
-   iavf
-   ice
+   device_drivers/freescale/dpaa2/index
+   device_drivers/intel/e100
+   device_drivers/intel/e1000
+   device_drivers/intel/e1000e
+   device_drivers/intel/fm10k
+   device_drivers/intel/igb
+   device_drivers/intel/igbvf
+   device_drivers/intel/ixgb
+   device_drivers/intel/ixgbe
+   device_drivers/intel/ixgbevf
+   device_drivers/intel/i40e
+   device_drivers/intel/iavf
+   device_drivers/intel/ice
    kapi
    z8530book
    msg_zerocopy
index fe46d48..18c1415 100644 (file)
@@ -7,7 +7,7 @@ Intro
 =====
 
 The MSG_ZEROCOPY flag enables copy avoidance for socket send calls.
-The feature is currently implemented for TCP sockets.
+The feature is currently implemented for TCP and UDP sockets.
 
 
 Opportunity and Caveats
index 355c6d8..b203d13 100644 (file)
@@ -22,8 +22,9 @@ and changeable from userspace under certain rules.
 2. Querying from userspace
 
 Both admin and operational state can be queried via the netlink
-operation RTM_GETLINK. It is also possible to subscribe to RTMGRP_LINK
-to be notified of updates. This is important for setting from userspace.
+operation RTM_GETLINK. It is also possible to subscribe to RTNLGRP_LINK
+to be notified of updates while the interface is admin up. This is
+important for setting from userspace.
 
 These values contain interface state:
 
@@ -101,8 +102,9 @@ because some driver controlled protocol establishment has to
 complete. Corresponding functions are netif_dormant_on() to set the
 flag, netif_dormant_off() to clear it and netif_dormant() to query.
 
-On device allocation, networking core sets the flags equivalent to
-netif_carrier_ok() and !netif_dormant().
+On device allocation, both flags __LINK_STATE_NOCARRIER and
+__LINK_STATE_DORMANT are cleared, so the effective state is equivalent
+to netif_carrier_ok() and !netif_dormant().
 
 
 Whenever the driver CHANGES one of these flags, a workqueue event is
@@ -133,11 +135,11 @@ netif_carrier_ok() && !netif_dormant() is set by the
 driver. Afterwards, the userspace application can set IFLA_OPERSTATE
 to IF_OPER_DORMANT or IF_OPER_UP as long as the driver does not set
 netif_carrier_off() or netif_dormant_on(). Changes made by userspace
-are multicasted on the netlink group RTMGRP_LINK.
+are multicasted on the netlink group RTNLGRP_LINK.
 
 So basically a 802.1X supplicant interacts with the kernel like this:
 
--subscribe to RTMGRP_LINK
+-subscribe to RTNLGRP_LINK
 -set IFLA_LINKMODE to 1 via RTM_SETLINK
 -query RTM_GETLINK once to get initial state
 -if initial flags are not (IFF_LOWER_UP && !IFF_DORMANT), wait until
index c9d052e..2df5894 100644 (file)
@@ -1000,51 +1000,6 @@ The kernel interface functions are as follows:
      size should be set when the call is begun.  tx_total_len may not be less
      than zero.
 
- (*) Check to see the completion state of a call so that the caller can assess
-     whether it needs to be retried.
-
-       enum rxrpc_call_completion {
-               RXRPC_CALL_SUCCEEDED,
-               RXRPC_CALL_REMOTELY_ABORTED,
-               RXRPC_CALL_LOCALLY_ABORTED,
-               RXRPC_CALL_LOCAL_ERROR,
-               RXRPC_CALL_NETWORK_ERROR,
-       };
-
-       int rxrpc_kernel_check_call(struct socket *sock, struct rxrpc_call *call,
-                                   enum rxrpc_call_completion *_compl,
-                                   u32 *_abort_code);
-
-     On return, -EINPROGRESS will be returned if the call is still ongoing; if
-     it is finished, *_compl will be set to indicate the manner of completion,
-     *_abort_code will be set to any abort code that occurred.  0 will be
-     returned on a successful completion, -ECONNABORTED will be returned if the
-     client failed due to a remote abort and anything else will return an
-     appropriate error code.
-
-     The caller should look at this information to decide if it's worth
-     retrying the call.
-
- (*) Retry a client call.
-
-       int rxrpc_kernel_retry_call(struct socket *sock,
-                                   struct rxrpc_call *call,
-                                   struct sockaddr_rxrpc *srx,
-                                   struct key *key);
-
-     This attempts to partially reinitialise a call and submit it again while
-     reusing the original call's Tx queue to avoid the need to repackage and
-     re-encrypt the data to be sent.  call indicates the call to retry, srx the
-     new address to send it to and key the encryption key to use for signing or
-     encrypting the packets.
-
-     For this to work, the first Tx data packet must still be in the transmit
-     queue, and currently this is only permitted for local and network errors
-     and the call must not have been aborted.  Any partially constructed Tx
-     packet is left as is and can continue being filled afterwards.
-
-     It returns 0 if the call was requeued and an error otherwise.
-
  (*) Get call RTT.
 
        u64 rxrpc_kernel_get_rtt(struct socket *sock, struct rxrpc_call *call);
index b0dfdaa..fe8f741 100644 (file)
@@ -336,7 +336,26 @@ time client replies ACK, this socket will get another chance to move
 to the accept queue.
 
 
-TCP Fast Open
+* TcpEstabResets
+Defined in `RFC1213 tcpEstabResets`_.
+
+.. _RFC1213 tcpEstabResets: https://tools.ietf.org/html/rfc1213#page-48
+
+* TcpAttemptFails
+Defined in `RFC1213 tcpAttemptFails`_.
+
+.. _RFC1213 tcpAttemptFails: https://tools.ietf.org/html/rfc1213#page-48
+
+* TcpOutRsts
+Defined in `RFC1213 tcpOutRsts`_. The RFC says this counter indicates
+the 'segments sent containing the RST flag', but in linux kernel, this
+couner indicates the segments kerenl tried to send. The sending
+process might be failed due to some errors (e.g. memory alloc failed).
+
+.. _RFC1213 tcpOutRsts: https://tools.ietf.org/html/rfc1213#page-52
+
+
+TCP Fast Path
 ============
 When kernel receives a TCP packet, it has two paths to handler the
 packet, one is fast path, another is slow path. The comment in kernel
@@ -383,8 +402,6 @@ increase 1.
 
 TCP abort
 ========
-
-
 * TcpExtTCPAbortOnData
 It means TCP layer has data in flight, but need to close the
 connection. So TCP layer sends a RST to the other side, indicate the
@@ -545,7 +562,6 @@ packet yet, the sender would know packet 4 is out of order. The TCP
 stack of kernel will increase TcpExtTCPSACKReorder for both of the
 above scenarios.
 
-
 DSACK
 =====
 The DSACK is defined in `RFC2883`_. The receiver uses DSACK to report
@@ -566,13 +582,63 @@ The TCP stack receives an out of order duplicate packet, so it sends a
 DSACK to the sender.
 
 * TcpExtTCPDSACKRecv
-The TCP stack receives a DSACK, which indicate an acknowledged
+The TCP stack receives a DSACK, which indicates an acknowledged
 duplicate packet is received.
 
 * TcpExtTCPDSACKOfoRecv
 The TCP stack receives a DSACK, which indicate an out of order
 duplicate packet is received.
 
+invalid SACK and DSACK
+====================
+When a SACK (or DSACK) block is invalid, a corresponding counter would
+be updated. The validation method is base on the start/end sequence
+number of the SACK block. For more details, please refer the comment
+of the function tcp_is_sackblock_valid in the kernel source code. A
+SACK option could have up to 4 blocks, they are checked
+individually. E.g., if 3 blocks of a SACk is invalid, the
+corresponding counter would be updated 3 times. The comment of the
+`Add counters for discarded SACK blocks`_ patch has additional
+explaination:
+
+.. _Add counters for discarded SACK blocks: https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/commit/?id=18f02545a9a16c9a89778b91a162ad16d510bb32
+
+* TcpExtTCPSACKDiscard
+This counter indicates how many SACK blocks are invalid. If the invalid
+SACK block is caused by ACK recording, the TCP stack will only ignore
+it and won't update this counter.
+
+* TcpExtTCPDSACKIgnoredOld and TcpExtTCPDSACKIgnoredNoUndo
+When a DSACK block is invalid, one of these two counters would be
+updated. Which counter will be updated depends on the undo_marker flag
+of the TCP socket. If the undo_marker is not set, the TCP stack isn't
+likely to re-transmit any packets, and we still receive an invalid
+DSACK block, the reason might be that the packet is duplicated in the
+middle of the network. In such scenario, TcpExtTCPDSACKIgnoredNoUndo
+will be updated. If the undo_marker is set, TcpExtTCPDSACKIgnoredOld
+will be updated. As implied in its name, it might be an old packet.
+
+SACK shift
+=========
+The linux networking stack stores data in sk_buff struct (skb for
+short). If a SACK block acrosses multiple skb, the TCP stack will try
+to re-arrange data in these skb. E.g. if a SACK block acknowledges seq
+10 to 15, skb1 has seq 10 to 13, skb2 has seq 14 to 20. The seq 14 and
+15 in skb2 would be moved to skb1. This operation is 'shift'. If a
+SACK block acknowledges seq 10 to 20, skb1 has seq 10 to 13, skb2 has
+seq 14 to 20. All data in skb2 will be moved to skb1, and skb2 will be
+discard, this operation is 'merge'.
+
+* TcpExtTCPSackShifted
+A skb is shifted
+
+* TcpExtTCPSackMerged
+A skb is merged
+
+* TcpExtTCPSackShiftFallback
+A skb should be shifted or merged, but the TCP stack doesn't do it for
+some reasons.
+
 TCP out of order
 ===============
 * TcpExtTCPOFOQueue
@@ -662,6 +728,60 @@ unacknowledged number (more strict than `RFC 5961 section 5.2`_).
 .. _RFC 5961 section 4.2: https://tools.ietf.org/html/rfc5961#page-9
 .. _RFC 5961 section 5.2: https://tools.ietf.org/html/rfc5961#page-11
 
+TCP receive window
+=================
+* TcpExtTCPWantZeroWindowAdv
+Depending on current memory usage, the TCP stack tries to set receive
+window to zero. But the receive window might still be a no-zero
+value. For example, if the previous window size is 10, and the TCP
+stack receives 3 bytes, the current window size would be 7 even if the
+window size calculated by the memory usage is zero.
+
+* TcpExtTCPToZeroWindowAdv
+The TCP receive window is set to zero from a no-zero value.
+
+* TcpExtTCPFromZeroWindowAdv
+The TCP receive window is set to no-zero value from zero.
+
+
+Delayed ACK
+==========
+The TCP Delayed ACK is a technique which is used for reducing the
+packet count in the network. For more details, please refer the
+`Delayed ACK wiki`_
+
+.. _Delayed ACK wiki: https://en.wikipedia.org/wiki/TCP_delayed_acknowledgment
+
+* TcpExtDelayedACKs
+A delayed ACK timer expires. The TCP stack will send a pure ACK packet
+and exit the delayed ACK mode.
+
+* TcpExtDelayedACKLocked
+A delayed ACK timer expires, but the TCP stack can't send an ACK
+immediately due to the socket is locked by a userspace program. The
+TCP stack will send a pure ACK later (after the userspace program
+unlock the socket). When the TCP stack sends the pure ACK later, the
+TCP stack will also update TcpExtDelayedACKs and exit the delayed ACK
+mode.
+
+* TcpExtDelayedACKLost
+It will be updated when the TCP stack receives a packet which has been
+ACKed. A Delayed ACK loss might cause this issue, but it would also be
+triggered by other reasons, such as a packet is duplicated in the
+network.
+
+Tail Loss Probe (TLP)
+===================
+TLP is an algorithm which is used to detect TCP packet loss. For more
+details, please refer the `TLP paper`_.
+
+.. _TLP paper: https://tools.ietf.org/html/draft-dukkipati-tcpm-tcp-loss-probe-01
+
+* TcpExtTCPLossProbes
+A TLP probe packet is sent.
+
+* TcpExtTCPLossProbeRecovery
+A packet loss is detected and recovered by TLP.
 
 examples
 =======
index 82236a1..97b7ca8 100644 (file)
@@ -92,11 +92,11 @@ device.
 Switch ID
 ^^^^^^^^^
 
-The switchdev driver must implement the switchdev op switchdev_port_attr_get
-for SWITCHDEV_ATTR_ID_PORT_PARENT_ID for each port netdev, returning the same
-physical ID for each port of a switch.  The ID must be unique between switches
-on the same system.  The ID does not need to be unique between switches on
-different systems.
+The switchdev driver must implement the net_device operation
+ndo_get_port_parent_id for each port netdev, returning the same physical ID for
+each port of a switch. The ID must be unique between switches on the same
+system. The ID does not need to be unique between switches on different
+systems.
 
 The switch ID is used to locate ports on a switch and to know if aggregated
 ports belong to the same switch.
index 1be0b6f..9d1432e 100644 (file)
@@ -417,7 +417,7 @@ is again deprecated and ts[2] holds a hardware timestamp if set.
 
 Hardware time stamping must also be initialized for each device driver
 that is expected to do hardware time stamping. The parameter is defined in
-/include/linux/net_tstamp.h as:
+include/uapi/linux/net_tstamp.h as:
 
 struct hwtstamp_config {
        int flags;      /* no flags defined right now, must be zero */
@@ -487,7 +487,7 @@ enum {
        HWTSTAMP_FILTER_PTP_V1_L4_EVENT,
 
        /* for the complete list of values, please check
-        * the include file /include/linux/net_tstamp.h
+        * the include file include/uapi/linux/net_tstamp.h
         */
 };
 
index dc2ddc3..fbb9297 100644 (file)
@@ -216,14 +216,14 @@ You can use the ``interdiff`` program (http://cyberelk.net/tim/patchutils/) to
 generate a patch representing the differences between two patches and then
 apply the result.
 
-This will let you move from something like 4.7.2 to 4.7.3 in a single
+This will let you move from something like 5.7.2 to 5.7.3 in a single
 step. The -z flag to interdiff will even let you feed it patches in gzip or
 bzip2 compressed form directly without the use of zcat or bzcat or manual
 decompression.
 
-Here's how you'd go from 4.7.2 to 4.7.3 in a single step::
+Here's how you'd go from 5.7.2 to 5.7.3 in a single step::
 
-       interdiff -z ../patch-4.7.2.gz ../patch-4.7.3.gz | patch -p1
+       interdiff -z ../patch-5.7.2.gz ../patch-5.7.3.gz | patch -p1
 
 Although interdiff may save you a step or two you are generally advised to
 do the additional steps since interdiff can get things wrong in some cases.
@@ -245,62 +245,67 @@ The patches are available at http://kernel.org/
 Most recent patches are linked from the front page, but they also have
 specific homes.
 
-The 4.x.y (-stable) and 4.x patches live at
+The 5.x.y (-stable) and 5.x patches live at
 
-       https://www.kernel.org/pub/linux/kernel/v4.x/
+       https://www.kernel.org/pub/linux/kernel/v5.x/
 
-The -rc patches live at
+The -rc patches are not stored on the webserver but are generated on
+demand from git tags such as
 
-       https://www.kernel.org/pub/linux/kernel/v4.x/testing/
+       https://git.kernel.org/torvalds/p/v5.1-rc1/v5.0
 
+The stable -rc patches live at
 
-The 4.x kernels
+       https://www.kernel.org/pub/linux/kernel/v5.x/stable-review/
+
+
+The 5.x kernels
 ===============
 
 These are the base stable releases released by Linus. The highest numbered
 release is the most recent.
 
 If regressions or other serious flaws are found, then a -stable fix patch
-will be released (see below) on top of this base. Once a new 4.x base
+will be released (see below) on top of this base. Once a new 5.x base
 kernel is released, a patch is made available that is a delta between the
-previous 4.x kernel and the new one.
+previous 5.x kernel and the new one.
 
-To apply a patch moving from 4.6 to 4.7, you'd do the following (note
-that such patches do **NOT** apply on top of 4.x.y kernels but on top of the
-base 4.x kernel -- if you need to move from 4.x.y to 4.x+1 you need to
-first revert the 4.x.y patch).
+To apply a patch moving from 5.6 to 5.7, you'd do the following (note
+that such patches do **NOT** apply on top of 5.x.y kernels but on top of the
+base 5.x kernel -- if you need to move from 5.x.y to 5.x+1 you need to
+first revert the 5.x.y patch).
 
 Here are some examples::
 
-       # moving from 4.6 to 4.7
+       # moving from 5.6 to 5.7
 
-       $ cd ~/linux-4.6                # change to kernel source dir
-       $ patch -p1 < ../patch-4.7      # apply the 4.7 patch
+       $ cd ~/linux-5.6                # change to kernel source dir
+       $ patch -p1 < ../patch-5.7      # apply the 5.7 patch
        $ cd ..
-       $ mv linux-4.6 linux-4.7        # rename source dir
+       $ mv linux-5.6 linux-5.7        # rename source dir
 
-       # moving from 4.6.1 to 4.7
+       # moving from 5.6.1 to 5.7
 
-       $ cd ~/linux-4.6.1              # change to kernel source dir
-       $ patch -p1 -R < ../patch-4.6.1 # revert the 4.6.1 patch
-                                       # source dir is now 4.6
-       $ patch -p1 < ../patch-4.7      # apply new 4.7 patch
+       $ cd ~/linux-5.6.1              # change to kernel source dir
+       $ patch -p1 -R < ../patch-5.6.1 # revert the 5.6.1 patch
+                                       # source dir is now 5.6
+       $ patch -p1 < ../patch-5.7      # apply new 5.7 patch
        $ cd ..
-       $ mv linux-4.6.1 linux-4.7      # rename source dir
+       $ mv linux-5.6.1 linux-5.7      # rename source dir
 
 
-The 4.x.y kernels
+The 5.x.y kernels
 =================
 
 Kernels with 3-digit versions are -stable kernels. They contain small(ish)
 critical fixes for security problems or significant regressions discovered
-in a given 4.x kernel.
+in a given 5.x kernel.
 
 This is the recommended branch for users who want the most recent stable
 kernel and are not interested in helping test development/experimental
 versions.
 
-If no 4.x.y kernel is available, then the highest numbered 4.x kernel is
+If no 5.x.y kernel is available, then the highest numbered 5.x kernel is
 the current stable kernel.
 
 .. note::
@@ -308,23 +313,23 @@ the current stable kernel.
  The -stable team usually do make incremental patches available as well
  as patches against the latest mainline release, but I only cover the
  non-incremental ones below. The incremental ones can be found at
- https://www.kernel.org/pub/linux/kernel/v4.x/incr/
+ https://www.kernel.org/pub/linux/kernel/v5.x/incr/
 
-These patches are not incremental, meaning that for example the 4.7.3
-patch does not apply on top of the 4.7.2 kernel source, but rather on top
-of the base 4.7 kernel source.
+These patches are not incremental, meaning that for example the 5.7.3
+patch does not apply on top of the 5.7.2 kernel source, but rather on top
+of the base 5.7 kernel source.
 
-So, in order to apply the 4.7.3 patch to your existing 4.7.2 kernel
-source you have to first back out the 4.7.2 patch (so you are left with a
-base 4.7 kernel source) and then apply the new 4.7.3 patch.
+So, in order to apply the 5.7.3 patch to your existing 5.7.2 kernel
+source you have to first back out the 5.7.2 patch (so you are left with a
+base 5.7 kernel source) and then apply the new 5.7.3 patch.
 
 Here's a small example::
 
-       $ cd ~/linux-4.7.2              # change to the kernel source dir
-       $ patch -p1 -R < ../patch-4.7.2 # revert the 4.7.2 patch
-       $ patch -p1 < ../patch-4.7.3    # apply the new 4.7.3 patch
+       $ cd ~/linux-5.7.2              # change to the kernel source dir
+       $ patch -p1 -R < ../patch-5.7.2 # revert the 5.7.2 patch
+       $ patch -p1 < ../patch-5.7.3    # apply the new 5.7.3 patch
        $ cd ..
-       $ mv linux-4.7.2 linux-4.7.3    # rename the kernel source dir
+       $ mv linux-5.7.2 linux-5.7.3    # rename the kernel source dir
 
 The -rc kernels
 ===============
@@ -343,38 +348,38 @@ This is a good branch to run for people who want to help out testing
 development kernels but do not want to run some of the really experimental
 stuff (such people should see the sections about -next and -mm kernels below).
 
-The -rc patches are not incremental, they apply to a base 4.x kernel, just
-like the 4.x.y patches described above. The kernel version before the -rcN
+The -rc patches are not incremental, they apply to a base 5.x kernel, just
+like the 5.x.y patches described above. The kernel version before the -rcN
 suffix denotes the version of the kernel that this -rc kernel will eventually
 turn into.
 
-So, 4.8-rc5 means that this is the fifth release candidate for the 4.8
-kernel and the patch should be applied on top of the 4.7 kernel source.
+So, 5.8-rc5 means that this is the fifth release candidate for the 5.8
+kernel and the patch should be applied on top of the 5.7 kernel source.
 
 Here are 3 examples of how to apply these patches::
 
-       # first an example of moving from 4.7 to 4.8-rc3
+       # first an example of moving from 5.7 to 5.8-rc3
 
-       $ cd ~/linux-4.7                        # change to the 4.7 source dir
-       $ patch -p1 < ../patch-4.8-rc3          # apply the 4.8-rc3 patch
+       $ cd ~/linux-5.7                        # change to the 5.7 source dir
+       $ patch -p1 < ../patch-5.8-rc3          # apply the 5.8-rc3 patch
        $ cd ..
-       $ mv linux-4.7 linux-4.8-rc3            # rename the source dir
+       $ mv linux-5.7 linux-5.8-rc3            # rename the source dir
 
-       # now let's move from 4.8-rc3 to 4.8-rc5
+       # now let's move from 5.8-rc3 to 5.8-rc5
 
-       $ cd ~/linux-4.8-rc3                    # change to the 4.8-rc3 dir
-       $ patch -p1 -R < ../patch-4.8-rc3       # revert the 4.8-rc3 patch
-       $ patch -p1 < ../patch-4.8-rc5          # apply the new 4.8-rc5 patch
+       $ cd ~/linux-5.8-rc3                    # change to the 5.8-rc3 dir
+       $ patch -p1 -R < ../patch-5.8-rc3       # revert the 5.8-rc3 patch
+       $ patch -p1 < ../patch-5.8-rc5          # apply the new 5.8-rc5 patch
        $ cd ..
-       $ mv linux-4.8-rc3 linux-4.8-rc5        # rename the source dir
+       $ mv linux-5.8-rc3 linux-5.8-rc5        # rename the source dir
 
-       # finally let's try and move from 4.7.3 to 4.8-rc5
+       # finally let's try and move from 5.7.3 to 5.8-rc5
 
-       $ cd ~/linux-4.7.3                      # change to the kernel source dir
-       $ patch -p1 -R < ../patch-4.7.3         # revert the 4.7.3 patch
-       $ patch -p1 < ../patch-4.8-rc5          # apply new 4.8-rc5 patch
+       $ cd ~/linux-5.7.3                      # change to the kernel source dir
+       $ patch -p1 -R < ../patch-5.7.3         # revert the 5.7.3 patch
+       $ patch -p1 < ../patch-5.8-rc5          # apply new 5.8-rc5 patch
        $ cd ..
-       $ mv linux-4.7.3 linux-4.8-rc5          # rename the kernel source dir
+       $ mv linux-5.7.3 linux-5.8-rc5          # rename the kernel source dir
 
 
 The -mm patches and the linux-next tree
index 819caf8..ebc679b 100644 (file)
@@ -56,26 +56,34 @@ of any kernel data structures.
 
 dentry-state:
 
-From linux/fs/dentry.c:
+From linux/include/linux/dcache.h:
 --------------------------------------------------------------
-struct {
+struct dentry_stat_t dentry_stat {
         int nr_dentry;
         int nr_unused;
         int age_limit;         /* age in seconds */
         int want_pages;        /* pages requested by system */
-        int dummy[2];
-} dentry_stat = {0, 0, 45, 0,};
--------------------------------------------------------------- 
-
-Dentries are dynamically allocated and deallocated, and
-nr_dentry seems to be 0 all the time. Hence it's safe to
-assume that only nr_unused, age_limit and want_pages are
-used. Nr_unused seems to be exactly what its name says.
+        int nr_negative;       /* # of unused negative dentries */
+        int dummy;             /* Reserved for future use */
+};
+--------------------------------------------------------------
+
+Dentries are dynamically allocated and deallocated.
+
+nr_dentry shows the total number of dentries allocated (active
++ unused). nr_unused shows the number of dentries that are not
+actively used, but are saved in the LRU list for future reuse.
+
 Age_limit is the age in seconds after which dcache entries
 can be reclaimed when memory is short and want_pages is
 nonzero when shrink_dcache_pages() has been called and the
 dcache isn't pruned yet.
 
+nr_negative shows the number of unused dentries that are also
+negative dentries which do not map to any files. Instead,
+they help speeding up rejection of non-existing files provided
+by the users.
+
 ==============================================================
 
 dquot-max & dquot-nr:
index 89ab09e..f07e380 100644 (file)
@@ -165,7 +165,7 @@ Do some work...
 The same can also be done from an application program.
 
 Disable specific CPU's specific idle state from cpuidle sysfs (see
-Documentation/cpuidle/sysfs.txt):
+Documentation/admin-guide/pm/cpuidle.rst):
 # echo 1 > /sys/devices/system/cpu/cpu$cpu/cpuidle/state$state/disable
 
 
index 80f5ffc..b371668 100644 (file)
@@ -4,7 +4,7 @@
 
 .. _it_readme:
 
-Rilascio del kernel Linux  4.x <http://kernel.org/>
+Rilascio del kernel Linux  5.x <http://kernel.org/>
 ===================================================
 
 .. warning::
index 71d6d25..659bbc0 100644 (file)
@@ -242,6 +242,6 @@ References
 ==========
 
 .. [white-paper] http://amd-dev.wpengine.netdna-cdn.com/wordpress/media/2013/12/AMD_Memory_Encryption_Whitepaper_v7-Public.pdf
-.. [api-spec] http://support.amd.com/TechDocs/55766_SEV-KM%20API_Specification.pdf
+.. [api-spec] http://support.amd.com/TechDocs/55766_SEV-KM_API_Specification.pdf
 .. [amd-apm] http://support.amd.com/TechDocs/24593.pdf (section 15.34)
 .. [kvm-forum]  http://www.linux-kvm.org/images/7/74/02x08A-Thomas_Lendacky-AMDs_Virtualizatoin_Memory_Encryption_Technology.pdf
index d9aed83..c1f95b5 100644 (file)
@@ -9,7 +9,7 @@ Fenghua Yu <fenghua.yu@intel.com>
 Tony Luck <tony.luck@intel.com>
 Vikas Shivappa <vikas.shivappa@intel.com>
 
-This feature is enabled by the CONFIG_RESCTRL and the X86 /proc/cpuinfo
+This feature is enabled by the CONFIG_X86_CPU_RESCTRL and the x86 /proc/cpuinfo
 flag bits:
 RDT (Resource Director Technology) Allocation - "rdt_a"
 CAT (Cache Allocation Technology) - "cat_l3", "cat_l2"
index 32d4444..dce5c09 100644 (file)
@@ -409,8 +409,7 @@ F:  drivers/platform/x86/wmi.c
 F:     include/uapi/linux/wmi.h
 
 AD1889 ALSA SOUND DRIVER
-M:     Thibaut Varene <T-Bone@parisc-linux.org>
-W:     http://wiki.parisc-linux.org/AD1889
+W:     https://parisc.wiki.kernel.org/index.php/AD1889
 L:     linux-parisc@vger.kernel.org
 S:     Maintained
 F:     sound/pci/ad1889.*
@@ -2848,8 +2847,11 @@ F:       include/uapi/linux/if_bonding.h
 BPF (Safe dynamic programs and tools)
 M:     Alexei Starovoitov <ast@kernel.org>
 M:     Daniel Borkmann <daniel@iogearbox.net>
+R:     Martin KaFai Lau <kafai@fb.com>
+R:     Song Liu <songliubraving@fb.com>
+R:     Yonghong Song <yhs@fb.com>
 L:     netdev@vger.kernel.org
-L:     linux-kernel@vger.kernel.org
+L:     bpf@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf.git
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/bpf/bpf-next.git
 Q:     https://patchwork.ozlabs.org/project/netdev/list/?delegate=77147
@@ -2873,10 +2875,13 @@ F:      samples/bpf/
 F:     tools/bpf/
 F:     tools/lib/bpf/
 F:     tools/testing/selftests/bpf/
+K:     bpf
+N:     bpf
 
 BPF JIT for ARM
 M:     Shubham Bansal <illusionist.neo@gmail.com>
 L:     netdev@vger.kernel.org
+L:     bpf@vger.kernel.org
 S:     Maintained
 F:     arch/arm/net/
 
@@ -2885,18 +2890,21 @@ M:      Daniel Borkmann <daniel@iogearbox.net>
 M:     Alexei Starovoitov <ast@kernel.org>
 M:     Zi Shen Lim <zlim.lnx@gmail.com>
 L:     netdev@vger.kernel.org
+L:     bpf@vger.kernel.org
 S:     Supported
 F:     arch/arm64/net/
 
 BPF JIT for MIPS (32-BIT AND 64-BIT)
 M:     Paul Burton <paul.burton@mips.com>
 L:     netdev@vger.kernel.org
+L:     bpf@vger.kernel.org
 S:     Maintained
 F:     arch/mips/net/
 
 BPF JIT for NFP NICs
 M:     Jakub Kicinski <jakub.kicinski@netronome.com>
 L:     netdev@vger.kernel.org
+L:     bpf@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/netronome/nfp/bpf/
 
@@ -2904,6 +2912,7 @@ BPF JIT for POWERPC (32-BIT AND 64-BIT)
 M:     Naveen N. Rao <naveen.n.rao@linux.ibm.com>
 M:     Sandipan Das <sandipan@linux.ibm.com>
 L:     netdev@vger.kernel.org
+L:     bpf@vger.kernel.org
 S:     Maintained
 F:     arch/powerpc/net/
 
@@ -2911,6 +2920,7 @@ BPF JIT for S390
 M:     Martin Schwidefsky <schwidefsky@de.ibm.com>
 M:     Heiko Carstens <heiko.carstens@de.ibm.com>
 L:     netdev@vger.kernel.org
+L:     bpf@vger.kernel.org
 S:     Maintained
 F:     arch/s390/net/
 X:     arch/s390/net/pnet.c
@@ -2918,12 +2928,14 @@ X:      arch/s390/net/pnet.c
 BPF JIT for SPARC (32-BIT AND 64-BIT)
 M:     David S. Miller <davem@davemloft.net>
 L:     netdev@vger.kernel.org
+L:     bpf@vger.kernel.org
 S:     Maintained
 F:     arch/sparc/net/
 
 BPF JIT for X86 32-BIT
 M:     Wang YanQing <udknight@gmail.com>
 L:     netdev@vger.kernel.org
+L:     bpf@vger.kernel.org
 S:     Maintained
 F:     arch/x86/net/bpf_jit_comp32.c
 
@@ -2931,6 +2943,7 @@ BPF JIT for X86 64-BIT
 M:     Alexei Starovoitov <ast@kernel.org>
 M:     Daniel Borkmann <daniel@iogearbox.net>
 L:     netdev@vger.kernel.org
+L:     bpf@vger.kernel.org
 S:     Supported
 F:     arch/x86/net/
 X:     arch/x86/net/bpf_jit_comp32.c
@@ -3052,8 +3065,8 @@ F:        include/linux/bcm963xx_nvram.h
 F:     include/linux/bcm963xx_tag.h
 
 BROADCOM BNX2 GIGABIT ETHERNET DRIVER
-M:     Rasesh Mody <rasesh.mody@cavium.com>
-M:     Dept-GELinuxNICDev@cavium.com
+M:     Rasesh Mody <rmody@marvell.com>
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/broadcom/bnx2.*
@@ -3072,9 +3085,9 @@ S:        Supported
 F:     drivers/scsi/bnx2i/
 
 BROADCOM BNX2X 10 GIGABIT ETHERNET DRIVER
-M:     Ariel Elior <ariel.elior@cavium.com>
-M:     Sudarsana Kalluru <sudarsana.kalluru@cavium.com>
-M:     everest-linux-l2@cavium.com
+M:     Ariel Elior <aelior@marvell.com>
+M:     Sudarsana Kalluru <skalluru@marvell.com>
+M:     GR-everest-linux-l2@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/broadcom/bnx2x/
@@ -3249,9 +3262,9 @@ S:        Supported
 F:     drivers/scsi/bfa/
 
 BROCADE BNA 10 GIGABIT ETHERNET DRIVER
-M:     Rasesh Mody <rasesh.mody@cavium.com>
-M:     Sudarsana Kalluru <sudarsana.kalluru@cavium.com>
-M:     Dept-GELinuxNICDev@cavium.com
+M:     Rasesh Mody <rmody@marvell.com>
+M:     Sudarsana Kalluru <skalluru@marvell.com>
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/brocade/bna/
@@ -3385,9 +3398,8 @@ F:        Documentation/media/v4l-drivers/cafe_ccic*
 F:     drivers/media/platform/marvell-ccic/
 
 CAIF NETWORK LAYER
-M:     Dmitry Tarnyagin <dmitry.tarnyagin@lockless.no>
 L:     netdev@vger.kernel.org
-S:     Supported
+S:     Orphan
 F:     Documentation/networking/caif/
 F:     drivers/net/caif/
 F:     include/uapi/linux/caif/
@@ -3471,10 +3483,9 @@ F:       drivers/i2c/busses/i2c-octeon*
 F:     drivers/i2c/busses/i2c-thunderx*
 
 CAVIUM LIQUIDIO NETWORK DRIVER
-M:     Derek Chickles <derek.chickles@caviumnetworks.com>
-M:     Satanand Burla <satananda.burla@caviumnetworks.com>
-M:     Felix Manlunas <felix.manlunas@caviumnetworks.com>
-M:     Raghu Vatsavayi <raghu.vatsavayi@caviumnetworks.com>
+M:     Derek Chickles <dchickles@marvell.com>
+M:     Satanand Burla <sburla@marvell.com>
+M:     Felix Manlunas <fmanlunas@marvell.com>
 L:     netdev@vger.kernel.org
 W:     http://www.cavium.com
 S:     Supported
@@ -3951,7 +3962,7 @@ L:        netdev@vger.kernel.org
 S:     Maintained
 F:     drivers/net/ethernet/ti/cpmac.c
 
-CPU FREQUENCY DRIVERS
+CPU FREQUENCY SCALING FRAMEWORK
 M:     "Rafael J. Wysocki" <rjw@rjwysocki.net>
 M:     Viresh Kumar <viresh.kumar@linaro.org>
 L:     linux-pm@vger.kernel.org
@@ -3959,6 +3970,8 @@ S:        Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
 T:     git git://git.linaro.org/people/vireshk/linux.git (For ARM Updates)
 B:     https://bugzilla.kernel.org
+F:     Documentation/admin-guide/pm/cpufreq.rst
+F:     Documentation/admin-guide/pm/intel_pstate.rst
 F:     Documentation/cpu-freq/
 F:     Documentation/devicetree/bindings/cpufreq/
 F:     drivers/cpufreq/
@@ -3977,6 +3990,7 @@ F:        drivers/cpufreq/arm_big_little.c
 CPU POWER MONITORING SUBSYSTEM
 M:     Thomas Renninger <trenn@suse.com>
 M:     Shuah Khan <shuah@kernel.org>
+M:     Shuah Khan <skhan@linuxfoundation.org>
 L:     linux-pm@vger.kernel.org
 S:     Maintained
 F:     tools/power/cpupower/
@@ -4006,13 +4020,14 @@ S:      Supported
 F:     drivers/cpuidle/cpuidle-exynos.c
 F:     arch/arm/mach-exynos/pm.c
 
-CPUIDLE DRIVERS
+CPU IDLE TIME MANAGEMENT FRAMEWORK
 M:     "Rafael J. Wysocki" <rjw@rjwysocki.net>
 M:     Daniel Lezcano <daniel.lezcano@linaro.org>
 L:     linux-pm@vger.kernel.org
 S:     Maintained
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/rafael/linux-pm.git
 B:     https://bugzilla.kernel.org
+F:     Documentation/admin-guide/pm/cpuidle.rst
 F:     drivers/cpuidle/*
 F:     include/linux/cpuidle.h
 
@@ -5178,7 +5193,7 @@ DRM DRIVERS FOR XEN
 M:     Oleksandr Andrushchenko <oleksandr_andrushchenko@epam.com>
 T:     git git://anongit.freedesktop.org/drm/drm-misc
 L:     dri-devel@lists.freedesktop.org
-L:     xen-devel@lists.xen.org
+L:     xen-devel@lists.xenproject.org (moderated for non-subscribers)
 S:     Supported
 F:     drivers/gpu/drm/xen/
 F:     Documentation/gpu/xen-front.rst
@@ -6143,7 +6158,7 @@ FREESCALE SOC SOUND DRIVERS
 M:     Timur Tabi <timur@kernel.org>
 M:     Nicolin Chen <nicoleotsuka@gmail.com>
 M:     Xiubo Li <Xiubo.Lee@gmail.com>
-R:     Fabio Estevam <fabio.estevam@nxp.com>
+R:     Fabio Estevam <festevam@gmail.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 L:     linuxppc-dev@lists.ozlabs.org
 S:     Maintained
@@ -8256,6 +8271,7 @@ F:        include/uapi/linux/sunrpc/
 
 KERNEL SELFTEST FRAMEWORK
 M:     Shuah Khan <shuah@kernel.org>
+M:     Shuah Khan <skhan@linuxfoundation.org>
 L:     linux-kselftest@vger.kernel.org
 T:     git git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest.git
 Q:     https://patchwork.kernel.org/project/linux-kselftest/list/
@@ -8478,6 +8494,7 @@ L7 BPF FRAMEWORK
 M:     John Fastabend <john.fastabend@gmail.com>
 M:     Daniel Borkmann <daniel@iogearbox.net>
 L:     netdev@vger.kernel.org
+L:     bpf@vger.kernel.org
 S:     Maintained
 F:     include/linux/skmsg.h
 F:     net/core/skmsg.c
@@ -10686,9 +10703,9 @@ S:      Maintained
 F:     drivers/net/netdevsim/*
 
 NETXEN (1/10) GbE SUPPORT
-M:     Manish Chopra <manish.chopra@cavium.com>
-M:     Rahul Verma <rahul.verma@cavium.com>
-M:     Dept-GELinuxNICDev@cavium.com
+M:     Manish Chopra <manishc@marvell.com>
+M:     Rahul Verma <rahulv@marvell.com>
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/netxen/
@@ -10889,7 +10906,7 @@ F:      include/linux/nvmem-consumer.h
 F:     include/linux/nvmem-provider.h
 
 NXP SGTL5000 DRIVER
-M:     Fabio Estevam <fabio.estevam@nxp.com>
+M:     Fabio Estevam <festevam@gmail.com>
 L:     alsa-devel@alsa-project.org (moderated for non-subscribers)
 S:     Maintained
 F:     Documentation/devicetree/bindings/sound/sgtl5000.txt
@@ -11303,10 +11320,12 @@ F:    include/dt-bindings/
 
 OPENCORES I2C BUS DRIVER
 M:     Peter Korsgaard <peter@korsgaard.com>
+M:     Andrew Lunn <andrew@lunn.ch>
 L:     linux-i2c@vger.kernel.org
 S:     Maintained
 F:     Documentation/i2c/busses/i2c-ocores
 F:     drivers/i2c/busses/i2c-ocores.c
+F:     include/linux/platform_data/i2c-ocores.h
 
 OPENRISC ARCHITECTURE
 M:     Jonas Bonn <jonas@southpole.se>
@@ -11477,7 +11496,7 @@ F:      Documentation/blockdev/paride.txt
 F:     drivers/block/paride/
 
 PARISC ARCHITECTURE
-M:     "James E.J. Bottomley" <jejb@parisc-linux.org>
+M:     "James E.J. Bottomley" <James.Bottomley@HansenPartnership.com>
 M:     Helge Deller <deller@gmx.de>
 L:     linux-parisc@vger.kernel.org
 W:     http://www.parisc-linux.org/
@@ -12472,8 +12491,8 @@ S:      Supported
 F:     drivers/scsi/qedi/
 
 QLOGIC QL4xxx ETHERNET DRIVER
-M:     Ariel Elior <Ariel.Elior@cavium.com>
-M:     everest-linux-l2@cavium.com
+M:     Ariel Elior <aelior@marvell.com>
+M:     GR-everest-linux-l2@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/qed/
@@ -12481,8 +12500,8 @@ F:      include/linux/qed/
 F:     drivers/net/ethernet/qlogic/qede/
 
 QLOGIC QL4xxx RDMA DRIVER
-M:     Michal Kalderon <Michal.Kalderon@cavium.com>
-M:     Ariel Elior <Ariel.Elior@cavium.com>
+M:     Michal Kalderon <mkalderon@marvell.com>
+M:     Ariel Elior <aelior@marvell.com>
 L:     linux-rdma@vger.kernel.org
 S:     Supported
 F:     drivers/infiniband/hw/qedr/
@@ -12502,7 +12521,7 @@ F:      Documentation/scsi/LICENSE.qla2xxx
 F:     drivers/scsi/qla2xxx/
 
 QLOGIC QLA3XXX NETWORK DRIVER
-M:     Dept-GELinuxNICDev@cavium.com
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     Documentation/networking/device_drivers/qlogic/LICENSE.qla3xxx
@@ -12516,16 +12535,16 @@ F:    Documentation/scsi/LICENSE.qla4xxx
 F:     drivers/scsi/qla4xxx/
 
 QLOGIC QLCNIC (1/10)Gb ETHERNET DRIVER
-M:     Shahed Shaikh <Shahed.Shaikh@cavium.com>
-M:     Manish Chopra <manish.chopra@cavium.com>
-M:     Dept-GELinuxNICDev@cavium.com
+M:     Shahed Shaikh <shshaikh@marvell.com>
+M:     Manish Chopra <manishc@marvell.com>
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/qlcnic/
 
 QLOGIC QLGE 10Gb ETHERNET DRIVER
-M:     Manish Chopra <manish.chopra@cavium.com>
-M:     Dept-GELinuxNICDev@cavium.com
+M:     Manish Chopra <manishc@marvell.com>
+M:     GR-Linux-NIC-Dev@marvell.com
 L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/qlogic/qlge/
@@ -12864,6 +12883,13 @@ F:     Documentation/devicetree/bindings/net/dsa/realtek-smi.txt
 F:     drivers/net/dsa/realtek-smi*
 F:     drivers/net/dsa/rtl83*
 
+REDPINE WIRELESS DRIVER
+M:     Amitkumar Karwar <amitkarwar@gmail.com>
+M:     Siva Rebbagondla <siva8118@gmail.com>
+L:     linux-wireless@vger.kernel.org
+S:     Maintained
+F:     drivers/net/wireless/rsi/
+
 REGISTER MAP ABSTRACTION
 M:     Mark Brown <broonie@kernel.org>
 L:     linux-kernel@vger.kernel.org
@@ -13692,6 +13718,15 @@ L:     netdev@vger.kernel.org
 S:     Supported
 F:     drivers/net/ethernet/sfc/
 
+SFF/SFP/SFP+ MODULE SUPPORT
+M:     Russell King <linux@armlinux.org.uk>
+L:     netdev@vger.kernel.org
+S:     Maintained
+F:     drivers/net/phy/phylink.c
+F:     drivers/net/phy/sfp*
+F:     include/linux/phylink.h
+F:     include/linux/sfp.h
+
 SGI GRU DRIVER
 M:     Dimitri Sivanich <sivanich@sgi.com>
 S:     Maintained
@@ -13820,8 +13855,9 @@ F:      drivers/media/mmc/siano/
 
 SIFIVE DRIVERS
 M:     Palmer Dabbelt <palmer@sifive.com>
+M:     Paul Walmsley <paul.walmsley@sifive.com>
 L:     linux-riscv@lists.infradead.org
-T:     git git://git.kernel.org/pub/scm/linux/kernel/git/palmer/riscv-linux.git
+T:     git git://github.com/sifive/riscv-linux.git
 S:     Supported
 K:     sifive
 N:     sifive
@@ -14432,6 +14468,11 @@ M:     Florian Schilhabel <florian.c.schilhabel@googlemail.com>.
 S:     Odd Fixes
 F:     drivers/staging/rtl8712/
 
+STAGING - REALTEK RTL8188EU DRIVERS
+M:     Larry Finger <Larry.Finger@lwfinger.net>
+S:     Odd Fixes
+F:     drivers/staging/rtl8188eu/
+
 STAGING - SILICON MOTION SM750 FRAME BUFFER DRIVER
 M:     Sudip Mukherjee <sudipm.mukherjee@gmail.com>
 M:     Teddy Wang <teddy.wang@siliconmotion.com>
@@ -15802,7 +15843,6 @@ M:      Alan Stern <stern@rowland.harvard.edu>
 L:     linux-usb@vger.kernel.org
 L:     usb-storage@lists.one-eyed-alien.net
 S:     Maintained
-W:     http://www.one-eyed-alien.net/~mdharm/linux-usb/
 F:     drivers/usb/storage/
 
 USB MIDI DRIVER
@@ -15834,6 +15874,7 @@ F:      drivers/usb/common/usb-otg-fsm.c
 USB OVER IP DRIVER
 M:     Valentina Manea <valentina.manea.m@gmail.com>
 M:     Shuah Khan <shuah@kernel.org>
+M:     Shuah Khan <skhan@linuxfoundation.org>
 L:     linux-usb@vger.kernel.org
 S:     Maintained
 F:     Documentation/usb/usbip_protocol.txt
@@ -16631,6 +16672,15 @@ S:     Maintained
 F:     drivers/platform/x86/
 F:     drivers/platform/olpc/
 
+X86 PLATFORM DRIVERS - ARCH
+R:     Darren Hart <dvhart@infradead.org>
+R:     Andy Shevchenko <andy@infradead.org>
+L:     platform-driver-x86@vger.kernel.org
+L:     x86@kernel.org
+T:     git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/core
+S:     Maintained
+F:     arch/x86/platform
+
 X86 VDSO
 M:     Andy Lutomirski <luto@kernel.org>
 L:     linux-kernel@vger.kernel.org
@@ -16663,10 +16713,30 @@ T:    git git://linuxtv.org/media_tree.git
 S:     Maintained
 F:     drivers/media/tuners/tuner-xc2028.*
 
+XDP (eXpress Data Path)
+M:     Alexei Starovoitov <ast@kernel.org>
+M:     Daniel Borkmann <daniel@iogearbox.net>
+M:     David S. Miller <davem@davemloft.net>
+M:     Jakub Kicinski <jakub.kicinski@netronome.com>
+M:     Jesper Dangaard Brouer <hawk@kernel.org>
+M:     John Fastabend <john.fastabend@gmail.com>
+L:     netdev@vger.kernel.org
+L:     xdp-newbies@vger.kernel.org
+L:     bpf@vger.kernel.org
+S:     Supported
+F:     net/core/xdp.c
+F:     include/net/xdp.h
+F:     kernel/bpf/devmap.c
+F:     kernel/bpf/cpumap.c
+F:     include/trace/events/xdp.h
+K:     xdp
+N:     xdp
+
 XDP SOCKETS (AF_XDP)
 M:     Björn Töpel <bjorn.topel@intel.com>
 M:     Magnus Karlsson <magnus.karlsson@intel.com>
 L:     netdev@vger.kernel.org
+L:     bpf@vger.kernel.org
 S:     Maintained
 F:     kernel/bpf/xskmap.c
 F:     net/xdp/
index 8c55b64..ac5ac28 100644 (file)
--- a/Makefile
+++ b/Makefile
@@ -2,7 +2,7 @@
 VERSION = 5
 PATCHLEVEL = 0
 SUBLEVEL = 0
-EXTRAVERSION = -rc1
+EXTRAVERSION = -rc8
 NAME = Shy Crocodile
 
 # *DOCUMENTATION*
@@ -955,6 +955,7 @@ ifdef CONFIG_STACK_VALIDATION
   endif
 endif
 
+PHONY += prepare0
 
 ifeq ($(KBUILD_EXTMOD),)
 core-y         += kernel/ certs/ mm/ fs/ ipc/ security/ crypto/ block/
@@ -1061,8 +1062,7 @@ scripts: scripts_basic scripts_dtc
 # archprepare is used in arch Makefiles and when processed asm symlink,
 # version.h and scripts_basic is processed / created.
 
-# Listed in dependency order
-PHONY += prepare archprepare prepare0 prepare1 prepare2 prepare3
+PHONY += prepare archprepare prepare1 prepare2 prepare3
 
 # prepare3 is used to check if we are building in a separate output directory,
 # and if so do:
@@ -1360,11 +1360,11 @@ mrproper: rm-dirs  := $(wildcard $(MRPROPER_DIRS))
 mrproper: rm-files := $(wildcard $(MRPROPER_FILES))
 mrproper-dirs      := $(addprefix _mrproper_,scripts)
 
-PHONY += $(mrproper-dirs) mrproper archmrproper
+PHONY += $(mrproper-dirs) mrproper
 $(mrproper-dirs):
        $(Q)$(MAKE) $(clean)=$(patsubst _mrproper_%,%,$@)
 
-mrproper: clean archmrproper $(mrproper-dirs)
+mrproper: clean $(mrproper-dirs)
        $(call cmd,rmdirs)
        $(call cmd,rmfiles)
 
index 4d17cac..432402c 100644 (file)
 
 #elif defined(CONFIG_ALPHA_DP264) || \
       defined(CONFIG_ALPHA_LYNX)  || \
-      defined(CONFIG_ALPHA_SHARK) || \
-      defined(CONFIG_ALPHA_EIGER)
+      defined(CONFIG_ALPHA_SHARK)
 # define NR_IRQS       64
 
 #elif defined(CONFIG_ALPHA_TITAN)
 #define NR_IRQS                80
 
 #elif defined(CONFIG_ALPHA_RAWHIDE) || \
-       defined(CONFIG_ALPHA_TAKARA)
+      defined(CONFIG_ALPHA_TAKARA) || \
+      defined(CONFIG_ALPHA_EIGER)
 # define NR_IRQS       128
 
 #elif defined(CONFIG_ALPHA_WILDFIRE)
index d73dc47..188fc92 100644 (file)
@@ -78,7 +78,7 @@ __load_new_mm_context(struct mm_struct *next_mm)
 /* Macro for exception fixup code to access integer registers.  */
 #define dpf_reg(r)                                                     \
        (((unsigned long *)regs)[(r) <= 8 ? (r) : (r) <= 15 ? (r)-16 :  \
-                                (r) <= 18 ? (r)+8 : (r)-10])
+                                (r) <= 18 ? (r)+10 : (r)-10])
 
 asmlinkage void
 do_page_fault(unsigned long address, unsigned long mmcsr,
index 376366a..d750b30 100644 (file)
@@ -191,7 +191,6 @@ config NR_CPUS
 
 config ARC_SMP_HALT_ON_RESET
        bool "Enable Halt-on-reset boot mode"
-       default y if ARC_UBOOT_SUPPORT
        help
          In SMP configuration cores can be configured as Halt-on-reset
          or they could all start at same time. For Halt-on-reset, non
@@ -407,6 +406,14 @@ config ARC_HAS_ACCL_REGS
          (also referred to as r58:r59). These can also be used by gcc as GPR so
          kernel needs to save/restore per process
 
+config ARC_IRQ_NO_AUTOSAVE
+       bool "Disable hardware autosave regfile on interrupts"
+       default n
+       help
+         On HS cores, taken interrupt auto saves the regfile on stack.
+         This is programmable and can be optionally disabled in which case
+         software INTERRUPT_PROLOGUE/EPILGUE do the needed work
+
 endif  # ISA_ARCV2
 
 endmenu   # "ARC CPU Configuration"
@@ -515,17 +522,6 @@ config ARC_DBG_TLB_PARANOIA
 
 endif
 
-config ARC_UBOOT_SUPPORT
-       bool "Support uboot arg Handling"
-       help
-         ARC Linux by default checks for uboot provided args as pointers to
-         external cmdline or DTB. This however breaks in absence of uboot,
-         when booting from Metaware debugger directly, as the registers are
-         not zeroed out on reset by mdb and/or ARCv2 based cores. The bogus
-         registers look like uboot args to kernel which then chokes.
-         So only enable the uboot arg checking/processing if users are sure
-         of uboot being in play.
-
 config ARC_BUILTIN_DTB_NAME
        string "Built in DTB"
        help
index 6e84060..621f594 100644 (file)
@@ -31,7 +31,6 @@ CONFIG_ARC_CACHE_LINE_SHIFT=5
 # CONFIG_ARC_HAS_LLSC is not set
 CONFIG_ARC_KVADDR_SIZE=402
 CONFIG_ARC_EMUL_UNALIGNED=y
-CONFIG_ARC_UBOOT_SUPPORT=y
 CONFIG_PREEMPT=y
 CONFIG_NET=y
 CONFIG_UNIX=y
index 1e59a2e..e447ace 100644 (file)
@@ -13,7 +13,6 @@ CONFIG_PARTITION_ADVANCED=y
 CONFIG_ARC_PLAT_AXS10X=y
 CONFIG_AXS103=y
 CONFIG_ISA_ARCV2=y
-CONFIG_ARC_UBOOT_SUPPORT=y
 CONFIG_ARC_BUILTIN_DTB_NAME="vdk_hs38"
 CONFIG_PREEMPT=y
 CONFIG_NET=y
index b5c3f6c..c82cdb1 100644 (file)
@@ -15,8 +15,6 @@ CONFIG_AXS103=y
 CONFIG_ISA_ARCV2=y
 CONFIG_SMP=y
 # CONFIG_ARC_TIMERS_64BIT is not set
-# CONFIG_ARC_SMP_HALT_ON_RESET is not set
-CONFIG_ARC_UBOOT_SUPPORT=y
 CONFIG_ARC_BUILTIN_DTB_NAME="vdk_hs38_smp"
 CONFIG_PREEMPT=y
 CONFIG_NET=y
index feed50c..caa2702 100644 (file)
@@ -3,23 +3,19 @@ generic-y += bugs.h
 generic-y += compat.h
 generic-y += device.h
 generic-y += div64.h
-generic-y += dma-mapping.h
 generic-y += emergency-restart.h
 generic-y += extable.h
-generic-y += fb.h
 generic-y += ftrace.h
 generic-y += hardirq.h
 generic-y += hw_irq.h
 generic-y += irq_regs.h
 generic-y += irq_work.h
-generic-y += kmap_types.h
 generic-y += local.h
 generic-y += local64.h
 generic-y += mcs_spinlock.h
 generic-y += mm-arch-hooks.h
 generic-y += msi.h
 generic-y += parport.h
-generic-y += pci.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += topology.h
index 49bfbd8..a27eafd 100644 (file)
@@ -151,6 +151,14 @@ struct bcr_isa_arcv2 {
 #endif
 };
 
+struct bcr_uarch_build_arcv2 {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad:8, prod:8, maj:8, min:8;
+#else
+       unsigned int min:8, maj:8, prod:8, pad:8;
+#endif
+};
+
 struct bcr_mpy {
 #ifdef CONFIG_CPU_BIG_ENDIAN
        unsigned int pad:8, x1616:8, dsp:4, cycles:2, type:2, ver:8;
@@ -216,6 +224,14 @@ struct bcr_fp_arcv2 {
 #endif
 };
 
+struct bcr_actionpoint {
+#ifdef CONFIG_CPU_BIG_ENDIAN
+       unsigned int pad:21, min:1, num:2, ver:8;
+#else
+       unsigned int ver:8, num:2, min:1, pad:21;
+#endif
+};
+
 #include <soc/arc/timers.h>
 
 struct bcr_bpu_arcompact {
@@ -283,7 +299,7 @@ struct cpuinfo_arc_cache {
 };
 
 struct cpuinfo_arc_bpu {
-       unsigned int ver, full, num_cache, num_pred;
+       unsigned int ver, full, num_cache, num_pred, ret_stk;
 };
 
 struct cpuinfo_arc_ccm {
@@ -302,7 +318,7 @@ struct cpuinfo_arc {
        struct {
                unsigned int swap:1, norm:1, minmax:1, barrel:1, crc:1, swape:1, pad1:2,
                             fpu_sp:1, fpu_dp:1, dual:1, dual_enb:1, pad2:4,
-                            debug:1, ap:1, smart:1, rtt:1, pad3:4,
+                            ap_num:4, ap_full:1, smart:1, rtt:1, pad3:1,
                             timer0:1, timer1:1, rtc:1, gfrc:1, pad4:4;
        } extn;
        struct bcr_mpy extn_mpy;
index ee92461..202b74c 100644 (file)
@@ -340,7 +340,7 @@ static inline __attribute__ ((const)) int __fls(unsigned long x)
 /*
  * __ffs: Similar to ffs, but zero based (0-31)
  */
-static inline __attribute__ ((const)) int __ffs(unsigned long word)
+static inline __attribute__ ((const)) unsigned long __ffs(unsigned long word)
 {
        if (!word)
                return word;
@@ -400,9 +400,9 @@ static inline __attribute__ ((const)) int ffs(unsigned long x)
 /*
  * __ffs: Similar to ffs, but zero based (0-31)
  */
-static inline __attribute__ ((const)) int __ffs(unsigned long x)
+static inline __attribute__ ((const)) unsigned long __ffs(unsigned long x)
 {
-       int n;
+       unsigned long n;
 
        asm volatile(
        "       ffs.f   %0, %1          \n"  /* 0:31; 31(Z) if src 0 */
index f393b66..2ad77fb 100644 (file)
 #define cache_line_size()      SMP_CACHE_BYTES
 #define ARCH_DMA_MINALIGN      SMP_CACHE_BYTES
 
+/*
+ * Make sure slab-allocated buffers are 64-bit aligned when atomic64_t uses
+ * ARCv2 64-bit atomics (LLOCKD/SCONDD). This guarantess runtime 64-bit
+ * alignment for any atomic64_t embedded in buffer.
+ * Default ARCH_SLAB_MINALIGN is __alignof__(long long) which has a relaxed
+ * value of 4 (and not 8) in ARC ABI.
+ */
+#if defined(CONFIG_ARC_HAS_LL64) && defined(CONFIG_ARC_HAS_LLSC)
+#define ARCH_SLAB_MINALIGN     8
+#endif
+
 extern void arc_cache_init(void);
 extern char *arc_cache_mumbojumbo(int cpu_id, char *buf, int len);
 extern void read_decode_cache_bcr(void);
index 309f4e6..225e7df 100644 (file)
        ;
        ; Now manually save: r12, sp, fp, gp, r25
 
+#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
+.ifnc \called_from, exception
+       st.as   r9, [sp, -10]   ; save r9 in it's final stack slot
+       sub     sp, sp, 12      ; skip JLI, LDI, EI
+
+       PUSH    lp_count
+       PUSHAX  lp_start
+       PUSHAX  lp_end
+       PUSH    blink
+
+       PUSH    r11
+       PUSH    r10
+
+       sub     sp, sp, 4       ; skip r9
+
+       PUSH    r8
+       PUSH    r7
+       PUSH    r6
+       PUSH    r5
+       PUSH    r4
+       PUSH    r3
+       PUSH    r2
+       PUSH    r1
+       PUSH    r0
+.endif
+#endif
+
 #ifdef CONFIG_ARC_HAS_ACCL_REGS
        PUSH    r59
        PUSH    r58
        POP     r59
 #endif
 
+#ifdef CONFIG_ARC_IRQ_NO_AUTOSAVE
+.ifnc \called_from, exception
+       POP     r0
+       POP     r1
+       POP     r2
+       POP     r3
+       POP     r4
+       POP     r5
+       POP     r6
+       POP     r7
+       POP     r8
+       POP     r9
+       POP     r10
+       POP     r11
+
+       POP     blink
+       POPAX   lp_end
+       POPAX   lp_start
+
+       POP     r9
+       mov     lp_count, r9
+
+       add     sp, sp, 12      ; skip JLI, LDI, EI
+       ld.as   r9, [sp, -10]   ; reload r9 which got clobbered
+.endif
+#endif
+
 .endm
 
 /*------------------------------------------------------------------------*/
index 9185541..6958545 100644 (file)
@@ -103,7 +103,8 @@ static const char * const arc_pmu_ev_hw_map[] = {
 
        /* counts condition */
        [PERF_COUNT_HW_INSTRUCTIONS] = "iall",
-       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmp", /* Excludes ZOL jumps */
+       /* All jump instructions that are taken */
+       [PERF_COUNT_HW_BRANCH_INSTRUCTIONS] = "ijmptak",
        [PERF_COUNT_ARC_BPOK]         = "bpok",   /* NP-NT, PT-T, PNT-NT */
 #ifdef CONFIG_ISA_ARCV2
        [PERF_COUNT_HW_BRANCH_MISSES] = "bpmp",
index c9173c0..eabc3ef 100644 (file)
@@ -207,7 +207,7 @@ raw_copy_from_user(void *to, const void __user *from, unsigned long n)
                */
                  "=&r" (tmp), "+r" (to), "+r" (from)
                :
-               : "lp_count", "lp_start", "lp_end", "memory");
+               : "lp_count", "memory");
 
                return n;
        }
@@ -433,7 +433,7 @@ raw_copy_to_user(void __user *to, const void *from, unsigned long n)
                 */
                  "=&r" (tmp), "+r" (to), "+r" (from)
                :
-               : "lp_count", "lp_start", "lp_end", "memory");
+               : "lp_count", "memory");
 
                return n;
        }
@@ -653,7 +653,7 @@ static inline unsigned long __arc_clear_user(void __user *to, unsigned long n)
        "       .previous                       \n"
        : "+r"(d_char), "+r"(res)
        : "i"(0)
-       : "lp_count", "lp_start", "lp_end", "memory");
+       : "lp_count", "memory");
 
        return res;
 }
@@ -686,7 +686,7 @@ __arc_strncpy_from_user(char *dst, const char __user *src, long count)
        "       .previous                       \n"
        : "+r"(res), "+r"(dst), "+r"(src), "=r"(val)
        : "g"(-EFAULT), "r"(count)
-       : "lp_count", "lp_start", "lp_end", "memory");
+       : "lp_count", "memory");
 
        return res;
 }
index cc558a2..562089d 100644 (file)
@@ -209,7 +209,9 @@ restore_regs:
 ;####### Return from Intr #######
 
 debug_marker_l1:
-       bbit1.nt r0, STATUS_DE_BIT, .Lintr_ret_to_delay_slot
+       ; bbit1.nt r0, STATUS_DE_BIT, .Lintr_ret_to_delay_slot
+       btst    r0, STATUS_DE_BIT               ; Z flag set if bit clear
+       bnz     .Lintr_ret_to_delay_slot        ; branch if STATUS_DE_BIT set
 
 .Lisr_ret_fast_path:
        ; Handle special case #1: (Entry via Exception, Return via IRQ)
index 8b90d25..30e0906 100644 (file)
@@ -17,6 +17,7 @@
 #include <asm/entry.h>
 #include <asm/arcregs.h>
 #include <asm/cache.h>
+#include <asm/irqflags.h>
 
 .macro CPU_EARLY_SETUP
 
        sr      r5, [ARC_REG_DC_CTRL]
 
 1:
+
+#ifdef CONFIG_ISA_ARCV2
+       ; Unaligned access is disabled at reset, so re-enable early as
+       ; gcc 7.3.1 (ARC GNU 2018.03) onwards generates unaligned access
+       ; by default
+       lr      r5, [status32]
+       bset    r5, r5, STATUS_AD_BIT
+       kflag   r5
+#endif
 .endm
 
        .section .init.text, "ax",@progbits
@@ -90,15 +100,13 @@ ENTRY(stext)
        st.ab   0, [r5, 4]
 1:
 
-#ifdef CONFIG_ARC_UBOOT_SUPPORT
        ; Uboot - kernel ABI
        ;    r0 = [0] No uboot interaction, [1] cmdline in r2, [2] DTB in r2
-       ;    r1 = magic number (board identity, unused as of now
+       ;    r1 = magic number (always zero as of now)
        ;    r2 = pointer to uboot provided cmdline or external DTB in mem
-       ; These are handled later in setup_arch()
+       ; These are handled later in handle_uboot_args()
        st      r0, [@uboot_tag]
        st      r2, [@uboot_arg]
-#endif
 
        ; setup "current" tsk and optionally cache it in dedicated r25
        mov     r9, @init_task
index 067ea36..cf18b3e 100644 (file)
@@ -49,11 +49,13 @@ void arc_init_IRQ(void)
 
        *(unsigned int *)&ictrl = 0;
 
+#ifndef CONFIG_ARC_IRQ_NO_AUTOSAVE
        ictrl.save_nr_gpr_pairs = 6;    /* r0 to r11 (r12 saved manually) */
        ictrl.save_blink = 1;
        ictrl.save_lp_regs = 1;         /* LP_COUNT, LP_START, LP_END */
        ictrl.save_u_to_u = 0;          /* user ctxt saved on kernel stack */
        ictrl.save_idx_regs = 1;        /* JLI, LDI, EI */
+#endif
 
        WRITE_AUX(AUX_IRQ_CTRL, ictrl);
 
index 8aec462..861a8ae 100644 (file)
@@ -1,15 +1,10 @@
-/*
- * Linux performance counter support for ARC700 series
- *
- * Copyright (C) 2013-2015 Synopsys, Inc. (www.synopsys.com)
- *
- * This code is inspired by the perf support of various other architectures.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
- */
+// SPDX-License-Identifier: GPL-2.0+
+//
+// Linux performance counter support for ARC CPUs.
+// This code is inspired by the perf support of various other architectures.
+//
+// Copyright (C) 2013-2018 Synopsys, Inc. (www.synopsys.com)
+
 #include <linux/errno.h>
 #include <linux/interrupt.h>
 #include <linux/module.h>
 #include <asm/arcregs.h>
 #include <asm/stacktrace.h>
 
+/* HW holds 8 symbols + one for null terminator */
+#define ARCPMU_EVENT_NAME_LEN  9
+
+enum arc_pmu_attr_groups {
+       ARCPMU_ATTR_GR_EVENTS,
+       ARCPMU_ATTR_GR_FORMATS,
+       ARCPMU_NR_ATTR_GR
+};
+
+struct arc_pmu_raw_event_entry {
+       char name[ARCPMU_EVENT_NAME_LEN];
+};
+
 struct arc_pmu {
        struct pmu      pmu;
        unsigned int    irq;
        int             n_counters;
+       int             n_events;
        u64             max_period;
        int             ev_hw_idx[PERF_COUNT_ARC_HW_MAX];
+
+       struct arc_pmu_raw_event_entry  *raw_entry;
+       struct attribute                **attrs;
+       struct perf_pmu_events_attr     *attr;
+       const struct attribute_group    *attr_groups[ARCPMU_NR_ATTR_GR + 1];
 };
 
 struct arc_pmu_cpu {
@@ -49,6 +63,7 @@ static int callchain_trace(unsigned int addr, void *data)
 {
        struct arc_callchain_trace *ctrl = data;
        struct perf_callchain_entry_ctx *entry = ctrl->perf_stuff;
+
        perf_callchain_store(entry, addr);
 
        if (ctrl->depth++ < 3)
@@ -57,8 +72,8 @@ static int callchain_trace(unsigned int addr, void *data)
        return -1;
 }
 
-void
-perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
+void perf_callchain_kernel(struct perf_callchain_entry_ctx *entry,
+                          struct pt_regs *regs)
 {
        struct arc_callchain_trace ctrl = {
                .depth = 0,
@@ -68,8 +83,8 @@ perf_callchain_kernel(struct perf_callchain_entry_ctx *entry, struct pt_regs *re
        arc_unwind_core(NULL, regs, callchain_trace, &ctrl);
 }
 
-void
-perf_callchain_user(struct perf_callchain_entry_ctx *entry, struct pt_regs *regs)
+void perf_callchain_user(struct perf_callchain_entry_ctx *entry,
+                        struct pt_regs *regs)
 {
        /*
         * User stack can't be unwound trivially with kernel dwarf unwinder
@@ -82,10 +97,10 @@ static struct arc_pmu *arc_pmu;
 static DEFINE_PER_CPU(struct arc_pmu_cpu, arc_pmu_cpu);
 
 /* read counter #idx; note that counter# != event# on ARC! */
-static uint64_t arc_pmu_read_counter(int idx)
+static u64 arc_pmu_read_counter(int idx)
 {
-       uint32_t tmp;
-       uint64_t result;
+       u32 tmp;
+       u64 result;
 
        /*
         * ARC supports making 'snapshots' of the counters, so we don't
@@ -94,7 +109,7 @@ static uint64_t arc_pmu_read_counter(int idx)
        write_aux_reg(ARC_REG_PCT_INDEX, idx);
        tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
        write_aux_reg(ARC_REG_PCT_CONTROL, tmp | ARC_REG_PCT_CONTROL_SN);
-       result = (uint64_t) (read_aux_reg(ARC_REG_PCT_SNAPH)) << 32;
+       result = (u64) (read_aux_reg(ARC_REG_PCT_SNAPH)) << 32;
        result |= read_aux_reg(ARC_REG_PCT_SNAPL);
 
        return result;
@@ -103,9 +118,9 @@ static uint64_t arc_pmu_read_counter(int idx)
 static void arc_perf_event_update(struct perf_event *event,
                                  struct hw_perf_event *hwc, int idx)
 {
-       uint64_t prev_raw_count = local64_read(&hwc->prev_count);
-       uint64_t new_raw_count = arc_pmu_read_counter(idx);
-       int64_t delta = new_raw_count - prev_raw_count;
+       u64 prev_raw_count = local64_read(&hwc->prev_count);
+       u64 new_raw_count = arc_pmu_read_counter(idx);
+       s64 delta = new_raw_count - prev_raw_count;
 
        /*
         * We aren't afraid of hwc->prev_count changing beneath our feet
@@ -155,7 +170,7 @@ static int arc_pmu_event_init(struct perf_event *event)
        int ret;
 
        if (!is_sampling_event(event)) {
-               hwc->sample_period  = arc_pmu->max_period;
+               hwc->sample_period = arc_pmu->max_period;
                hwc->last_period = hwc->sample_period;
                local64_set(&hwc->period_left, hwc->sample_period);
        }
@@ -192,6 +207,18 @@ static int arc_pmu_event_init(struct perf_event *event)
                pr_debug("init cache event with h/w %08x \'%s\'\n",
                         (int)hwc->config, arc_pmu_ev_hw_map[ret]);
                return 0;
+
+       case PERF_TYPE_RAW:
+               if (event->attr.config >= arc_pmu->n_events)
+                       return -ENOENT;
+
+               hwc->config |= event->attr.config;
+               pr_debug("init raw event with idx %lld \'%s\'\n",
+                        event->attr.config,
+                        arc_pmu->raw_entry[event->attr.config].name);
+
+               return 0;
+
        default:
                return -ENOENT;
        }
@@ -200,7 +227,7 @@ static int arc_pmu_event_init(struct perf_event *event)
 /* starts all counters */
 static void arc_pmu_enable(struct pmu *pmu)
 {
-       uint32_t tmp;
+       u32 tmp;
        tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
        write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x1);
 }
@@ -208,7 +235,7 @@ static void arc_pmu_enable(struct pmu *pmu)
 /* stops all counters */
 static void arc_pmu_disable(struct pmu *pmu)
 {
-       uint32_t tmp;
+       u32 tmp;
        tmp = read_aux_reg(ARC_REG_PCT_CONTROL);
        write_aux_reg(ARC_REG_PCT_CONTROL, (tmp & 0xffff0000) | 0x0);
 }
@@ -228,7 +255,7 @@ static int arc_pmu_event_set_period(struct perf_event *event)
                local64_set(&hwc->period_left, left);
                hwc->last_period = period;
                overflow = 1;
-       } else  if (unlikely(left <= 0)) {
+       } else if (unlikely(left <= 0)) {
                /* left underflowed by less than period. */
                left += period;
                local64_set(&hwc->period_left, left);
@@ -246,8 +273,8 @@ static int arc_pmu_event_set_period(struct perf_event *event)
        write_aux_reg(ARC_REG_PCT_INDEX, idx);
 
        /* Write value */
-       write_aux_reg(ARC_REG_PCT_COUNTL, (u32)value);
-       write_aux_reg(ARC_REG_PCT_COUNTH, (value >> 32));
+       write_aux_reg(ARC_REG_PCT_COUNTL, lower_32_bits(value));
+       write_aux_reg(ARC_REG_PCT_COUNTH, upper_32_bits(value));
 
        perf_event_update_userpage(event);
 
@@ -277,7 +304,7 @@ static void arc_pmu_start(struct perf_event *event, int flags)
        /* Enable interrupt for this counter */
        if (is_sampling_event(event))
                write_aux_reg(ARC_REG_PCT_INT_CTRL,
-                             read_aux_reg(ARC_REG_PCT_INT_CTRL) | (1 << idx));
+                             read_aux_reg(ARC_REG_PCT_INT_CTRL) | BIT(idx));
 
        /* enable ARC pmu here */
        write_aux_reg(ARC_REG_PCT_INDEX, idx);          /* counter # */
@@ -295,9 +322,9 @@ static void arc_pmu_stop(struct perf_event *event, int flags)
                 * Reset interrupt flag by writing of 1. This is required
                 * to make sure pending interrupt was not left.
                 */
-               write_aux_reg(ARC_REG_PCT_INT_ACT, 1 << idx);
+               write_aux_reg(ARC_REG_PCT_INT_ACT, BIT(idx));
                write_aux_reg(ARC_REG_PCT_INT_CTRL,
-                             read_aux_reg(ARC_REG_PCT_INT_CTRL) & ~(1 << idx));
+                             read_aux_reg(ARC_REG_PCT_INT_CTRL) & ~BIT(idx));
        }
 
        if (!(event->hw.state & PERF_HES_STOPPED)) {
@@ -349,9 +376,10 @@ static int arc_pmu_add(struct perf_event *event, int flags)
 
        if (is_sampling_event(event)) {
                /* Mimic full counter overflow as other arches do */
-               write_aux_reg(ARC_REG_PCT_INT_CNTL, (u32)arc_pmu->max_period);
+               write_aux_reg(ARC_REG_PCT_INT_CNTL,
+                             lower_32_bits(arc_pmu->max_period));
                write_aux_reg(ARC_REG_PCT_INT_CNTH,
-                             (arc_pmu->max_period >> 32));
+                             upper_32_bits(arc_pmu->max_period));
        }
 
        write_aux_reg(ARC_REG_PCT_CONFIG, 0);
@@ -392,7 +420,7 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
                idx = __ffs(active_ints);
 
                /* Reset interrupt flag by writing of 1 */
-               write_aux_reg(ARC_REG_PCT_INT_ACT, 1 << idx);
+               write_aux_reg(ARC_REG_PCT_INT_ACT, BIT(idx));
 
                /*
                 * On reset of "interrupt active" bit corresponding
@@ -400,7 +428,7 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
                 * Now we need to re-enable interrupt for the counter.
                 */
                write_aux_reg(ARC_REG_PCT_INT_CTRL,
-                       read_aux_reg(ARC_REG_PCT_INT_CTRL) | (1 << idx));
+                       read_aux_reg(ARC_REG_PCT_INT_CTRL) | BIT(idx));
 
                event = pmu_cpu->act_counter[idx];
                hwc = &event->hw;
@@ -414,7 +442,7 @@ static irqreturn_t arc_pmu_intr(int irq, void *dev)
                                arc_pmu_stop(event, 0);
                }
 
-               active_ints &= ~(1U << idx);
+               active_ints &= ~BIT(idx);
        } while (active_ints);
 
 done:
@@ -441,19 +469,108 @@ static void arc_cpu_pmu_irq_init(void *data)
        write_aux_reg(ARC_REG_PCT_INT_ACT, 0xffffffff);
 }
 
+/* Event field occupies the bottom 15 bits of our config field */
+PMU_FORMAT_ATTR(event, "config:0-14");
+static struct attribute *arc_pmu_format_attrs[] = {
+       &format_attr_event.attr,
+       NULL,
+};
+
+static struct attribute_group arc_pmu_format_attr_gr = {
+       .name = "format",
+       .attrs = arc_pmu_format_attrs,
+};
+
+static ssize_t arc_pmu_events_sysfs_show(struct device *dev,
+                                        struct device_attribute *attr,
+                                        char *page)
+{
+       struct perf_pmu_events_attr *pmu_attr;
+
+       pmu_attr = container_of(attr, struct perf_pmu_events_attr, attr);
+       return sprintf(page, "event=0x%04llx\n", pmu_attr->id);
+}
+
+/*
+ * We don't add attrs here as we don't have pre-defined list of perf events.
+ * We will generate and add attrs dynamically in probe() after we read HW
+ * configuration.
+ */
+static struct attribute_group arc_pmu_events_attr_gr = {
+       .name = "events",
+};
+
+static void arc_pmu_add_raw_event_attr(int j, char *str)
+{
+       memmove(arc_pmu->raw_entry[j].name, str, ARCPMU_EVENT_NAME_LEN - 1);
+       arc_pmu->attr[j].attr.attr.name = arc_pmu->raw_entry[j].name;
+       arc_pmu->attr[j].attr.attr.mode = VERIFY_OCTAL_PERMISSIONS(0444);
+       arc_pmu->attr[j].attr.show = arc_pmu_events_sysfs_show;
+       arc_pmu->attr[j].id = j;
+       arc_pmu->attrs[j] = &(arc_pmu->attr[j].attr.attr);
+}
+
+static int arc_pmu_raw_alloc(struct device *dev)
+{
+       arc_pmu->attr = devm_kmalloc_array(dev, arc_pmu->n_events + 1,
+               sizeof(*arc_pmu->attr), GFP_KERNEL | __GFP_ZERO);
+       if (!arc_pmu->attr)
+               return -ENOMEM;
+
+       arc_pmu->attrs = devm_kmalloc_array(dev, arc_pmu->n_events + 1,
+               sizeof(*arc_pmu->attrs), GFP_KERNEL | __GFP_ZERO);
+       if (!arc_pmu->attrs)
+               return -ENOMEM;
+
+       arc_pmu->raw_entry = devm_kmalloc_array(dev, arc_pmu->n_events,
+               sizeof(*arc_pmu->raw_entry), GFP_KERNEL | __GFP_ZERO);
+       if (!arc_pmu->raw_entry)
+               return -ENOMEM;
+
+       return 0;
+}
+
+static inline bool event_in_hw_event_map(int i, char *name)
+{
+       if (!arc_pmu_ev_hw_map[i])
+               return false;
+
+       if (!strlen(arc_pmu_ev_hw_map[i]))
+               return false;
+
+       if (strcmp(arc_pmu_ev_hw_map[i], name))
+               return false;
+
+       return true;
+}
+
+static void arc_pmu_map_hw_event(int j, char *str)
+{
+       int i;
+
+       /* See if HW condition has been mapped to a perf event_id */
+       for (i = 0; i < ARRAY_SIZE(arc_pmu_ev_hw_map); i++) {
+               if (event_in_hw_event_map(i, str)) {
+                       pr_debug("mapping perf event %2d to h/w event \'%8s\' (idx %d)\n",
+                                i, str, j);
+                       arc_pmu->ev_hw_idx[i] = j;
+               }
+       }
+}
+
 static int arc_pmu_device_probe(struct platform_device *pdev)
 {
        struct arc_reg_pct_build pct_bcr;
        struct arc_reg_cc_build cc_bcr;
-       int i, j, has_interrupts;
+       int i, has_interrupts;
        int counter_size;       /* in bits */
 
        union cc_name {
                struct {
-                       uint32_t word0, word1;
+                       u32 word0, word1;
                        char sentinel;
                } indiv;
-               char str[9];
+               char str[ARCPMU_EVENT_NAME_LEN];
        } cc_name;
 
 
@@ -463,15 +580,22 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
                return -ENODEV;
        }
        BUILD_BUG_ON(ARC_PERF_MAX_COUNTERS > 32);
-       BUG_ON(pct_bcr.c > ARC_PERF_MAX_COUNTERS);
+       if (WARN_ON(pct_bcr.c > ARC_PERF_MAX_COUNTERS))
+               return -EINVAL;
 
        READ_BCR(ARC_REG_CC_BUILD, cc_bcr);
-       BUG_ON(!cc_bcr.v); /* Counters exist but No countable conditions ? */
+       if (WARN(!cc_bcr.v, "Counters exist but No countable conditions?"))
+               return -EINVAL;
 
        arc_pmu = devm_kzalloc(&pdev->dev, sizeof(struct arc_pmu), GFP_KERNEL);
        if (!arc_pmu)
                return -ENOMEM;
 
+       arc_pmu->n_events = cc_bcr.c;
+
+       if (arc_pmu_raw_alloc(&pdev->dev))
+               return -ENOMEM;
+
        has_interrupts = is_isa_arcv2() ? pct_bcr.i : 0;
 
        arc_pmu->n_counters = pct_bcr.c;
@@ -481,30 +605,26 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
 
        pr_info("ARC perf\t: %d counters (%d bits), %d conditions%s\n",
                arc_pmu->n_counters, counter_size, cc_bcr.c,
-               has_interrupts ? ", [overflow IRQ support]":"");
+               has_interrupts ? ", [overflow IRQ support]" : "");
 
-       cc_name.str[8] = 0;
+       cc_name.str[ARCPMU_EVENT_NAME_LEN - 1] = 0;
        for (i = 0; i < PERF_COUNT_ARC_HW_MAX; i++)
                arc_pmu->ev_hw_idx[i] = -1;
 
        /* loop thru all available h/w condition indexes */
-       for (j = 0; j < cc_bcr.c; j++) {
-               write_aux_reg(ARC_REG_CC_INDEX, j);
+       for (i = 0; i < cc_bcr.c; i++) {
+               write_aux_reg(ARC_REG_CC_INDEX, i);
                cc_name.indiv.word0 = read_aux_reg(ARC_REG_CC_NAME0);
                cc_name.indiv.word1 = read_aux_reg(ARC_REG_CC_NAME1);
 
-               /* See if it has been mapped to a perf event_id */
-               for (i = 0; i < ARRAY_SIZE(arc_pmu_ev_hw_map); i++) {
-                       if (arc_pmu_ev_hw_map[i] &&
-                           !strcmp(arc_pmu_ev_hw_map[i], cc_name.str) &&
-                           strlen(arc_pmu_ev_hw_map[i])) {
-                               pr_debug("mapping perf event %2d to h/w event \'%8s\' (idx %d)\n",
-                                        i, cc_name.str, j);
-                               arc_pmu->ev_hw_idx[i] = j;
-                       }
-               }
+               arc_pmu_map_hw_event(i, cc_name.str);
+               arc_pmu_add_raw_event_attr(i, cc_name.str);
        }
 
+       arc_pmu_events_attr_gr.attrs = arc_pmu->attrs;
+       arc_pmu->attr_groups[ARCPMU_ATTR_GR_EVENTS] = &arc_pmu_events_attr_gr;
+       arc_pmu->attr_groups[ARCPMU_ATTR_GR_FORMATS] = &arc_pmu_format_attr_gr;
+
        arc_pmu->pmu = (struct pmu) {
                .pmu_enable     = arc_pmu_enable,
                .pmu_disable    = arc_pmu_disable,
@@ -514,6 +634,7 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
                .start          = arc_pmu_start,
                .stop           = arc_pmu_stop,
                .read           = arc_pmu_read,
+               .attr_groups    = arc_pmu->attr_groups,
        };
 
        if (has_interrupts) {
@@ -535,17 +656,19 @@ static int arc_pmu_device_probe(struct platform_device *pdev)
        } else
                arc_pmu->pmu.capabilities |= PERF_PMU_CAP_NO_INTERRUPT;
 
-       return perf_pmu_register(&arc_pmu->pmu, pdev->name, PERF_TYPE_RAW);
+       /*
+        * perf parser doesn't really like '-' symbol in events name, so let's
+        * use '_' in arc pct name as it goes to kernel PMU event prefix.
+        */
+       return perf_pmu_register(&arc_pmu->pmu, "arc_pct", PERF_TYPE_RAW);
 }
 
-#ifdef CONFIG_OF
 static const struct of_device_id arc_pmu_match[] = {
        { .compatible = "snps,arc700-pct" },
        { .compatible = "snps,archs-pct" },
        {},
 };
 MODULE_DEVICE_TABLE(of, arc_pmu_match);
-#endif
 
 static struct platform_driver arc_pmu_driver = {
        .driver = {
index 2e018b8..7b23409 100644 (file)
@@ -123,6 +123,7 @@ static void read_arc_build_cfg_regs(void)
        struct cpuinfo_arc *cpu = &cpuinfo_arc700[smp_processor_id()];
        const struct id_to_str *tbl;
        struct bcr_isa_arcv2 isa;
+       struct bcr_actionpoint ap;
 
        FIX_PTR(cpu);
 
@@ -195,20 +196,40 @@ static void read_arc_build_cfg_regs(void)
                cpu->bpu.full = bpu.ft;
                cpu->bpu.num_cache = 256 << bpu.bce;
                cpu->bpu.num_pred = 2048 << bpu.pte;
+               cpu->bpu.ret_stk = 4 << bpu.rse;
 
                if (cpu->core.family >= 0x54) {
-                       unsigned int exec_ctrl;
 
-                       READ_BCR(AUX_EXEC_CTRL, exec_ctrl);
-                       cpu->extn.dual_enb = !(exec_ctrl & 1);
+                       struct bcr_uarch_build_arcv2 uarch;
 
-                       /* dual issue always present for this core */
-                       cpu->extn.dual = 1;
+                       /*
+                        * The first 0x54 core (uarch maj:min 0:1 or 0:2) was
+                        * dual issue only (HS4x). But next uarch rev (1:0)
+                        * allows it be configured for single issue (HS3x)
+                        * Ensure we fiddle with dual issue only on HS4x
+                        */
+                       READ_BCR(ARC_REG_MICRO_ARCH_BCR, uarch);
+
+                       if (uarch.prod == 4) {
+                               unsigned int exec_ctrl;
+
+                               /* dual issue hardware always present */
+                               cpu->extn.dual = 1;
+
+                               READ_BCR(AUX_EXEC_CTRL, exec_ctrl);
+
+                               /* dual issue hardware enabled ? */
+                               cpu->extn.dual_enb = !(exec_ctrl & 1);
+
+                       }
                }
        }
 
-       READ_BCR(ARC_REG_AP_BCR, bcr);
-       cpu->extn.ap = bcr.ver ? 1 : 0;
+       READ_BCR(ARC_REG_AP_BCR, ap);
+       if (ap.ver) {
+               cpu->extn.ap_num = 2 << ap.num;
+               cpu->extn.ap_full = !ap.min;
+       }
 
        READ_BCR(ARC_REG_SMART_BCR, bcr);
        cpu->extn.smart = bcr.ver ? 1 : 0;
@@ -216,8 +237,6 @@ static void read_arc_build_cfg_regs(void)
        READ_BCR(ARC_REG_RTT_BCR, bcr);
        cpu->extn.rtt = bcr.ver ? 1 : 0;
 
-       cpu->extn.debug = cpu->extn.ap | cpu->extn.smart | cpu->extn.rtt;
-
        READ_BCR(ARC_REG_ISA_CFG_BCR, isa);
 
        /* some hacks for lack of feature BCR info in old ARC700 cores */
@@ -299,10 +318,10 @@ static char *arc_cpu_mumbojumbo(int cpu_id, char *buf, int len)
 
        if (cpu->bpu.ver)
                n += scnprintf(buf + n, len - n,
-                             "BPU\t\t: %s%s match, cache:%d, Predict Table:%d",
+                             "BPU\t\t: %s%s match, cache:%d, Predict Table:%d Return stk: %d",
                              IS_AVAIL1(cpu->bpu.full, "full"),
                              IS_AVAIL1(!cpu->bpu.full, "partial"),
-                             cpu->bpu.num_cache, cpu->bpu.num_pred);
+                             cpu->bpu.num_cache, cpu->bpu.num_pred, cpu->bpu.ret_stk);
 
        if (is_isa_arcv2()) {
                struct bcr_lpb lpb;
@@ -336,11 +355,17 @@ static char *arc_extn_mumbojumbo(int cpu_id, char *buf, int len)
                               IS_AVAIL1(cpu->extn.fpu_sp, "SP "),
                               IS_AVAIL1(cpu->extn.fpu_dp, "DP "));
 
-       if (cpu->extn.debug)
-               n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s%s\n",
-                              IS_AVAIL1(cpu->extn.ap, "ActionPoint "),
+       if (cpu->extn.ap_num | cpu->extn.smart | cpu->extn.rtt) {
+               n += scnprintf(buf + n, len - n, "DEBUG\t\t: %s%s",
                               IS_AVAIL1(cpu->extn.smart, "smaRT "),
                               IS_AVAIL1(cpu->extn.rtt, "RTT "));
+               if (cpu->extn.ap_num) {
+                       n += scnprintf(buf + n, len - n, "ActionPoint %d/%s",
+                                      cpu->extn.ap_num,
+                                      cpu->extn.ap_full ? "full":"min");
+               }
+               n += scnprintf(buf + n, len - n, "\n");
+       }
 
        if (cpu->dccm.sz || cpu->iccm.sz)
                n += scnprintf(buf + n, len - n, "Extn [CCM]\t: DCCM @ %x, %d KB / ICCM: @ %x, %d KB\n",
@@ -453,43 +478,78 @@ void setup_processor(void)
        arc_chk_core_config();
 }
 
-static inline int is_kernel(unsigned long addr)
+static inline bool uboot_arg_invalid(unsigned long addr)
 {
-       if (addr >= (unsigned long)_stext && addr <= (unsigned long)_end)
-               return 1;
-       return 0;
+       /*
+        * Check that it is a untranslated address (although MMU is not enabled
+        * yet, it being a high address ensures this is not by fluke)
+        */
+       if (addr < PAGE_OFFSET)
+               return true;
+
+       /* Check that address doesn't clobber resident kernel image */
+       return addr >= (unsigned long)_stext && addr <= (unsigned long)_end;
 }
 
-void __init setup_arch(char **cmdline_p)
+#define IGNORE_ARGS            "Ignore U-boot args: "
+
+/* uboot_tag values for U-boot - kernel ABI revision 0; see head.S */
+#define UBOOT_TAG_NONE         0
+#define UBOOT_TAG_CMDLINE      1
+#define UBOOT_TAG_DTB          2
+
+void __init handle_uboot_args(void)
 {
-#ifdef CONFIG_ARC_UBOOT_SUPPORT
-       /* make sure that uboot passed pointer to cmdline/dtb is valid */
-       if (uboot_tag && is_kernel((unsigned long)uboot_arg))
-               panic("Invalid uboot arg\n");
-
-       /* See if u-boot passed an external Device Tree blob */
-       machine_desc = setup_machine_fdt(uboot_arg);    /* uboot_tag == 2 */
-       if (!machine_desc)
-#endif
-       {
-               /* No, so try the embedded one */
+       bool use_embedded_dtb = true;
+       bool append_cmdline = false;
+
+       /* check that we know this tag */
+       if (uboot_tag != UBOOT_TAG_NONE &&
+           uboot_tag != UBOOT_TAG_CMDLINE &&
+           uboot_tag != UBOOT_TAG_DTB) {
+               pr_warn(IGNORE_ARGS "invalid uboot tag: '%08x'\n", uboot_tag);
+               goto ignore_uboot_args;
+       }
+
+       if (uboot_tag != UBOOT_TAG_NONE &&
+            uboot_arg_invalid((unsigned long)uboot_arg)) {
+               pr_warn(IGNORE_ARGS "invalid uboot arg: '%px'\n", uboot_arg);
+               goto ignore_uboot_args;
+       }
+
+       /* see if U-boot passed an external Device Tree blob */
+       if (uboot_tag == UBOOT_TAG_DTB) {
+               machine_desc = setup_machine_fdt((void *)uboot_arg);
+
+               /* external Device Tree blob is invalid - use embedded one */
+               use_embedded_dtb = !machine_desc;
+       }
+
+       if (uboot_tag == UBOOT_TAG_CMDLINE)
+               append_cmdline = true;
+
+ignore_uboot_args:
+
+       if (use_embedded_dtb) {
                machine_desc = setup_machine_fdt(__dtb_start);
                if (!machine_desc)
                        panic("Embedded DT invalid\n");
+       }
 
-               /*
-                * If we are here, it is established that @uboot_arg didn't
-                * point to DT blob. Instead if u-boot says it is cmdline,
-                * append to embedded DT cmdline.
-                * setup_machine_fdt() would have populated @boot_command_line
-                */
-               if (uboot_tag == 1) {
-                       /* Ensure a whitespace between the 2 cmdlines */
-                       strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
-                       strlcat(boot_command_line, uboot_arg,
-                               COMMAND_LINE_SIZE);
-               }
+       /*
+        * NOTE: @boot_command_line is populated by setup_machine_fdt() so this
+        * append processing can only happen after.
+        */
+       if (append_cmdline) {
+               /* Ensure a whitespace between the 2 cmdlines */
+               strlcat(boot_command_line, " ", COMMAND_LINE_SIZE);
+               strlcat(boot_command_line, uboot_arg, COMMAND_LINE_SIZE);
        }
+}
+
+void __init setup_arch(char **cmdline_p)
+{
+       handle_uboot_args();
 
        /* Save unparsed command line copy for /proc/cmdline */
        *cmdline_p = boot_command_line;
index e8d9fb4..215f515 100644 (file)
@@ -18,6 +18,8 @@
 #include <asm/arcregs.h>
 #include <asm/irqflags.h>
 
+#define ARC_PATH_MAX   256
+
 /*
  * Common routine to print scratch regs (r0-r12) or callee regs (r13-r25)
  *   -Prints 3 regs per line and a CR.
@@ -58,11 +60,12 @@ static void show_callee_regs(struct callee_regs *cregs)
        print_reg_file(&(cregs->r13), 13);
 }
 
-static void print_task_path_n_nm(struct task_struct *tsk, char *buf)
+static void print_task_path_n_nm(struct task_struct *tsk)
 {
        char *path_nm = NULL;
        struct mm_struct *mm;
        struct file *exe_file;
+       char buf[ARC_PATH_MAX];
 
        mm = get_task_mm(tsk);
        if (!mm)
@@ -72,7 +75,7 @@ static void print_task_path_n_nm(struct task_struct *tsk, char *buf)
        mmput(mm);
 
        if (exe_file) {
-               path_nm = file_path(exe_file, buf, 255);
+               path_nm = file_path(exe_file, buf, ARC_PATH_MAX-1);
                fput(exe_file);
        }
 
@@ -80,10 +83,9 @@ done:
        pr_info("Path: %s\n", !IS_ERR(path_nm) ? path_nm : "?");
 }
 
-static void show_faulting_vma(unsigned long address, char *buf)
+static void show_faulting_vma(unsigned long address)
 {
        struct vm_area_struct *vma;
-       char *nm = buf;
        struct mm_struct *active_mm = current->active_mm;
 
        /* can't use print_vma_addr() yet as it doesn't check for
@@ -96,8 +98,11 @@ static void show_faulting_vma(unsigned long address, char *buf)
         * if the container VMA is not found
         */
        if (vma && (vma->vm_start <= address)) {
+               char buf[ARC_PATH_MAX];
+               char *nm = "?";
+
                if (vma->vm_file) {
-                       nm = file_path(vma->vm_file, buf, PAGE_SIZE - 1);
+                       nm = file_path(vma->vm_file, buf, ARC_PATH_MAX-1);
                        if (IS_ERR(nm))
                                nm = "?";
                }
@@ -173,13 +178,14 @@ void show_regs(struct pt_regs *regs)
 {
        struct task_struct *tsk = current;
        struct callee_regs *cregs;
-       char *buf;
 
-       buf = (char *)__get_free_page(GFP_KERNEL);
-       if (!buf)
-               return;
+       /*
+        * generic code calls us with preemption disabled, but some calls
+        * here could sleep, so re-enable to avoid lockdep splat
+        */
+       preempt_enable();
 
-       print_task_path_n_nm(tsk, buf);
+       print_task_path_n_nm(tsk);
        show_regs_print_info(KERN_INFO);
 
        show_ecr_verbose(regs);
@@ -189,7 +195,7 @@ void show_regs(struct pt_regs *regs)
                (void *)regs->blink, (void *)regs->ret);
 
        if (user_mode(regs))
-               show_faulting_vma(regs->ret, buf); /* faulting code, not data */
+               show_faulting_vma(regs->ret); /* faulting code, not data */
 
        pr_info("[STAT32]: 0x%08lx", regs->status32);
 
@@ -222,7 +228,7 @@ void show_regs(struct pt_regs *regs)
        if (cregs)
                show_callee_regs(cregs);
 
-       free_page((unsigned long)buf);
+       preempt_disable();
 }
 
 void show_kernel_fault_diag(const char *str, struct pt_regs *regs,
index d61044d..ea14b0b 100644 (file)
 #endif
 
 #ifdef CONFIG_ARC_HAS_LL64
-# define PREFETCH_READ(RX)     prefetch    [RX, 56]
-# define PREFETCH_WRITE(RX)    prefetchw   [RX, 64]
 # define LOADX(DST,RX)         ldd.ab  DST, [RX, 8]
 # define STOREX(SRC,RX)                std.ab  SRC, [RX, 8]
 # define ZOLSHFT               5
 # define ZOLAND                        0x1F
 #else
-# define PREFETCH_READ(RX)     prefetch    [RX, 28]
-# define PREFETCH_WRITE(RX)    prefetchw   [RX, 32]
 # define LOADX(DST,RX)         ld.ab   DST, [RX, 4]
 # define STOREX(SRC,RX)                st.ab   SRC, [RX, 4]
 # define ZOLSHFT               4
@@ -41,8 +37,6 @@
 #endif
 
 ENTRY_CFI(memcpy)
-       prefetch [r1]           ; Prefetch the read location
-       prefetchw [r0]          ; Prefetch the write location
        mov.f   0, r2
 ;;; if size is zero
        jz.d    [blink]
@@ -72,8 +66,6 @@ ENTRY_CFI(memcpy)
        lpnz    @.Lcopy32_64bytes
        ;; LOOP START
        LOADX (r6, r1)
-       PREFETCH_READ (r1)
-       PREFETCH_WRITE (r3)
        LOADX (r8, r1)
        LOADX (r10, r1)
        LOADX (r4, r1)
@@ -117,9 +109,7 @@ ENTRY_CFI(memcpy)
        lpnz    @.Lcopy8bytes_1
        ;; LOOP START
        ld.ab   r6, [r1, 4]
-       prefetch [r1, 28]       ;Prefetch the next read location
        ld.ab   r8, [r1,4]
-       prefetchw [r3, 32]      ;Prefetch the next write location
 
        SHIFT_1 (r7, r6, 24)
        or      r7, r7, r5
@@ -162,9 +152,7 @@ ENTRY_CFI(memcpy)
        lpnz    @.Lcopy8bytes_2
        ;; LOOP START
        ld.ab   r6, [r1, 4]
-       prefetch [r1, 28]       ;Prefetch the next read location
        ld.ab   r8, [r1,4]
-       prefetchw [r3, 32]      ;Prefetch the next write location
 
        SHIFT_1 (r7, r6, 16)
        or      r7, r7, r5
@@ -204,9 +192,7 @@ ENTRY_CFI(memcpy)
        lpnz    @.Lcopy8bytes_3
        ;; LOOP START
        ld.ab   r6, [r1, 4]
-       prefetch [r1, 28]       ;Prefetch the next read location
        ld.ab   r8, [r1,4]
-       prefetchw [r3, 32]      ;Prefetch the next write location
 
        SHIFT_1 (r7, r6, 8)
        or      r7, r7, r5
index 62ad4bc..f230bb7 100644 (file)
@@ -7,11 +7,39 @@
  */
 
 #include <linux/linkage.h>
+#include <asm/cache.h>
 
-#undef PREALLOC_NOT_AVAIL
+/*
+ * The memset implementation below is optimized to use prefetchw and prealloc
+ * instruction in case of CPU with 64B L1 data cache line (L1_CACHE_SHIFT == 6)
+ * If you want to implement optimized memset for other possible L1 data cache
+ * line lengths (32B and 128B) you should rewrite code carefully checking
+ * we don't call any prefetchw/prealloc instruction for L1 cache lines which
+ * don't belongs to memset area.
+ */
+
+#if L1_CACHE_SHIFT == 6
+
+.macro PREALLOC_INSTR  reg, off
+       prealloc        [\reg, \off]
+.endm
+
+.macro PREFETCHW_INSTR reg, off
+       prefetchw       [\reg, \off]
+.endm
+
+#else
+
+.macro PREALLOC_INSTR
+.endm
+
+.macro PREFETCHW_INSTR
+.endm
+
+#endif
 
 ENTRY_CFI(memset)
-       prefetchw [r0]          ; Prefetch the write location
+       PREFETCHW_INSTR r0, 0   ; Prefetch the first write location
        mov.f   0, r2
 ;;; if size is zero
        jz.d    [blink]
@@ -48,11 +76,8 @@ ENTRY_CFI(memset)
 
        lpnz    @.Lset64bytes
        ;; LOOP START
-#ifdef PREALLOC_NOT_AVAIL
-       prefetchw [r3, 64]      ;Prefetch the next write location
-#else
-       prealloc  [r3, 64]
-#endif
+       PREALLOC_INSTR  r3, 64  ; alloc next line w/o fetching
+
 #ifdef CONFIG_ARC_HAS_LL64
        std.ab  r4, [r3, 8]
        std.ab  r4, [r3, 8]
@@ -85,7 +110,6 @@ ENTRY_CFI(memset)
        lsr.f   lp_count, r2, 5 ;Last remaining  max 124 bytes
        lpnz    .Lset32bytes
        ;; LOOP START
-       prefetchw   [r3, 32]    ;Prefetch the next write location
 #ifdef CONFIG_ARC_HAS_LL64
        std.ab  r4, [r3, 8]
        std.ab  r4, [r3, 8]
index a1d7231..8df1638 100644 (file)
@@ -141,12 +141,17 @@ good_area:
         */
        fault = handle_mm_fault(vma, address, flags);
 
-       /* If Pagefault was interrupted by SIGKILL, exit page fault "early" */
        if (fatal_signal_pending(current)) {
-               if ((fault & VM_FAULT_ERROR) && !(fault & VM_FAULT_RETRY))
-                       up_read(&mm->mmap_sem);
-               if (user_mode(regs))
+
+               /*
+                * if fault retry, mmap_sem already relinquished by core mm
+                * so OK to return to user mode (with signal handled first)
+                */
+               if (fault & VM_FAULT_RETRY) {
+                       if (!user_mode(regs))
+                               goto no_context;
                        return;
+               }
        }
 
        perf_sw_event(PERF_COUNT_SW_PAGE_FAULTS, 1, regs, address);
index 43bf4c3..e1ab2d7 100644 (file)
@@ -119,7 +119,8 @@ void __init setup_arch_memory(void)
         */
 
        memblock_add_node(low_mem_start, low_mem_sz, 0);
-       memblock_reserve(low_mem_start, __pa(_end) - low_mem_start);
+       memblock_reserve(CONFIG_LINUX_LINK_BASE,
+                        __pa(_end) - CONFIG_LINUX_LINK_BASE);
 
 #ifdef CONFIG_BLK_DEV_INITRD
        if (phys_initrd_size) {
index f25c085..23e0021 100644 (file)
@@ -9,6 +9,7 @@ menuconfig ARC_SOC_HSDK
        bool "ARC HS Development Kit SOC"
        depends on ISA_ARCV2
        select ARC_HAS_ACCL_REGS
+       select ARC_IRQ_NO_AUTOSAVE
        select CLK_HSDK
        select RESET_HSDK
        select HAVE_PCI
index 664e918..26524b7 100644 (file)
@@ -1400,6 +1400,7 @@ config NR_CPUS
 config HOTPLUG_CPU
        bool "Support for hot-pluggable CPUs"
        depends on SMP
+       select GENERIC_IRQ_MIGRATION
        help
          Say Y here to experiment with turning CPUs off and on.  CPUs
          can be controlled through /sys/devices/system/cpu.
index b67f5fe..dce5be5 100644 (file)
 
 &cpsw_emac0 {
        phy-handle = <&ethphy0>;
-       phy-mode = "rgmii-txid";
+       phy-mode = "rgmii-id";
 };
 
 &tscadc {
index 172c022..b128998 100644 (file)
 
 &cpsw_emac0 {
        phy-handle = <&ethphy0>;
-       phy-mode = "rgmii-txid";
+       phy-mode = "rgmii-id";
        dual_emac_res_vlan = <1>;
 };
 
 &cpsw_emac1 {
        phy-handle = <&ethphy1>;
-       phy-mode = "rgmii-txid";
+       phy-mode = "rgmii-id";
        dual_emac_res_vlan = <2>;
 };
 
index d0fd688..5b25006 100644 (file)
        pinctrl-names = "default";
        pinctrl-0 = <&mmc1_pins>;
        bus-width = <0x4>;
-       cd-gpios = <&gpio0 6 GPIO_ACTIVE_HIGH>;
+       cd-gpios = <&gpio0 6 GPIO_ACTIVE_LOW>;
        cd-inverted;
        max-frequency = <26000000>;
        vmmc-supply = <&vmmcsd_fixed>;
index f3ac748..5d04dc6 100644 (file)
                                status = "okay";
                        };
 
-                       nand@d0000 {
+                       nand-controller@d0000 {
                                status = "okay";
-                               label = "pxa3xx_nand-0";
-                               num-cs = <1>;
-                               marvell,nand-keep-config;
-                               nand-on-flash-bbt;
-
-                               partitions {
-                                       compatible = "fixed-partitions";
-                                       #address-cells = <1>;
-                                       #size-cells = <1>;
-
-                                       partition@0 {
-                                               label = "U-Boot";
-                                               reg = <0 0x800000>;
-                                       };
-                                       partition@800000 {
-                                               label = "Linux";
-                                               reg = <0x800000 0x800000>;
-                                       };
-                                       partition@1000000 {
-                                               label = "Filesystem";
-                                               reg = <0x1000000 0x3f000000>;
 
+                               nand@0 {
+                                       reg = <0>;
+                                       label = "pxa3xx_nand-0";
+                                       nand-rb = <0>;
+                                       nand-on-flash-bbt;
+
+                                       partitions {
+                                               compatible = "fixed-partitions";
+                                               #address-cells = <1>;
+                                               #size-cells = <1>;
+
+                                               partition@0 {
+                                                       label = "U-Boot";
+                                                       reg = <0 0x800000>;
+                                               };
+                                               partition@800000 {
+                                                       label = "Linux";
+                                                       reg = <0x800000 0x800000>;
+                                               };
+                                               partition@1000000 {
+                                                       label = "Filesystem";
+                                                       reg = <0x1000000 0x3f000000>;
+                                               };
                                        };
                                };
                        };
index 1139e94..b4cca50 100644 (file)
                                status = "okay";
                        };
 
-                       nand@d0000 {
+                       nand-controller@d0000 {
                                status = "okay";
-                               label = "pxa3xx_nand-0";
-                               num-cs = <1>;
-                               marvell,nand-keep-config;
-                               nand-on-flash-bbt;
+
+                               nand@0 {
+                                       reg = <0>;
+                                       label = "pxa3xx_nand-0";
+                                       nand-rb = <0>;
+                                       nand-on-flash-bbt;
+                               };
                        };
                };
 
index bbbb388..87dcb50 100644 (file)
 
                        };
 
-                       nand@d0000 {
+                       nand-controller@d0000 {
                                status = "okay";
-                               label = "pxa3xx_nand-0";
-                               num-cs = <1>;
-                               marvell,nand-keep-config;
-                               nand-on-flash-bbt;
-
-                               partitions {
-                                       compatible = "fixed-partitions";
-                                       #address-cells = <1>;
-                                       #size-cells = <1>;
-
-                                       partition@0 {
-                                               label = "u-boot";
-                                               reg = <0x00000000 0x000e0000>;
-                                               read-only;
-                                       };
-
-                                       partition@e0000 {
-                                               label = "u-boot-env";
-                                               reg = <0x000e0000 0x00020000>;
-                                               read-only;
-                                       };
-
-                                       partition@100000 {
-                                               label = "u-boot-env2";
-                                               reg = <0x00100000 0x00020000>;
-                                               read-only;
-                                       };
-
-                                       partition@120000 {
-                                               label = "zImage";
-                                               reg = <0x00120000 0x00400000>;
-                                       };
-
-                                       partition@520000 {
-                                               label = "initrd";
-                                               reg = <0x00520000 0x00400000>;
-                                       };
 
-                                       partition@e00000 {
-                                               label = "boot";
-                                               reg = <0x00e00000 0x3f200000>;
+                               nand@0 {
+                                       reg = <0>;
+                                       label = "pxa3xx_nand-0";
+                                       nand-rb = <0>;
+                                       nand-on-flash-bbt;
+
+                                       partitions {
+                                               compatible = "fixed-partitions";
+                                               #address-cells = <1>;
+                                               #size-cells = <1>;
+
+                                               partition@0 {
+                                                       label = "u-boot";
+                                                       reg = <0x00000000 0x000e0000>;
+                                                       read-only;
+                                               };
+
+                                               partition@e0000 {
+                                                       label = "u-boot-env";
+                                                       reg = <0x000e0000 0x00020000>;
+                                                       read-only;
+                                               };
+
+                                               partition@100000 {
+                                                       label = "u-boot-env2";
+                                                       reg = <0x00100000 0x00020000>;
+                                                       read-only;
+                                               };
+
+                                               partition@120000 {
+                                                       label = "zImage";
+                                                       reg = <0x00120000 0x00400000>;
+                                               };
+
+                                               partition@520000 {
+                                                       label = "initrd";
+                                                       reg = <0x00520000 0x00400000>;
+                                               };
+
+                                               partition@e00000 {
+                                                       label = "boot";
+                                                       reg = <0x00e00000 0x3f200000>;
+                                               };
                                        };
                                };
                        };
index a3c9b34..f04bc3e 100644 (file)
                regulator-boot-on;
        };
 
+       baseboard_3v3: fixedregulator-3v3 {
+               /* TPS73701DCQ */
+               compatible = "regulator-fixed";
+               regulator-name = "baseboard_3v3";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               vin-supply = <&vbat>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
+       baseboard_1v8: fixedregulator-1v8 {
+               /* TPS73701DCQ */
+               compatible = "regulator-fixed";
+               regulator-name = "baseboard_1v8";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vbat>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
        backlight_lcd: backlight-regulator {
                compatible = "regulator-fixed";
                regulator-name = "lcd_backlight_pwr";
 
        sound {
                compatible = "simple-audio-card";
-               simple-audio-card,name = "DA850/OMAP-L138 EVM";
+               simple-audio-card,name = "DA850-OMAPL138 EVM";
                simple-audio-card,widgets =
                        "Line", "Line In",
                        "Line", "Line Out";
 
                /* Regulators */
                IOVDD-supply = <&vdcdc2_reg>;
-               /* Derived from VBAT: Baseboard 3.3V / 1.8V */
-               AVDD-supply = <&vbat>;
-               DRVDD-supply = <&vbat>;
-               DVDD-supply = <&vbat>;
+               AVDD-supply = <&baseboard_3v3>;
+               DRVDD-supply = <&baseboard_3v3>;
+               DVDD-supply = <&baseboard_1v8>;
        };
        tca6416: gpio@20 {
                compatible = "ti,tca6416";
index 0177e3e..3a2fa6e 100644 (file)
                };
        };
 
+       vcc_5vd: fixedregulator-vcc_5vd {
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_5vd";
+               regulator-min-microvolt = <5000000>;
+               regulator-max-microvolt = <5000000>;
+               regulator-boot-on;
+       };
+
+       vcc_3v3d: fixedregulator-vcc_3v3d {
+               /* TPS650250 - VDCDC1 */
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_3v3d";
+               regulator-min-microvolt = <3300000>;
+               regulator-max-microvolt = <3300000>;
+               vin-supply = <&vcc_5vd>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
+       vcc_1v8d: fixedregulator-vcc_1v8d {
+               /* TPS650250 - VDCDC2 */
+               compatible = "regulator-fixed";
+               regulator-name = "vcc_1v8d";
+               regulator-min-microvolt = <1800000>;
+               regulator-max-microvolt = <1800000>;
+               vin-supply = <&vcc_5vd>;
+               regulator-always-on;
+               regulator-boot-on;
+       };
+
        sound {
                compatible = "simple-audio-card";
-               simple-audio-card,name = "DA850/OMAP-L138 LCDK";
+               simple-audio-card,name = "DA850-OMAPL138 LCDK";
                simple-audio-card,widgets =
                        "Line", "Line In",
                        "Line", "Line Out";
                compatible = "ti,tlv320aic3106";
                reg = <0x18>;
                status = "okay";
+
+               /* Regulators */
+               IOVDD-supply = <&vcc_3v3d>;
+               AVDD-supply = <&vcc_3v3d>;
+               DRVDD-supply = <&vcc_3v3d>;
+               DVDD-supply = <&vcc_1v8d>;
        };
 };
 
index 47aa53b..559659b 100644 (file)
                clocksource: timer@20000 {
                        compatible = "ti,da830-timer";
                        reg = <0x20000 0x1000>;
-                       interrupts = <12>, <13>;
+                       interrupts = <21>, <22>;
                        interrupt-names = "tint12", "tint34";
                        clocks = <&pll0_auxclk>;
                };
index 5edf858..a31b17e 100644 (file)
                power {
                        label = "Power Button";
                        gpios = <&gpio2 12 GPIO_ACTIVE_LOW>;
-                       gpio-key,wakeup;
+                       wakeup-source;
                        linux,code = <KEY_POWER>;
                };
        };
index d816370..4a31a41 100644 (file)
        pinctrl-2 = <&pinctrl_usdhc3_200mhz>;
        cd-gpios = <&gpio3 22 GPIO_ACTIVE_LOW>;
        keep-power-in-suspend;
-       enable-sdio-wakeup;
+       wakeup-source;
        vmmc-supply = <&reg_sd3_vmmc>;
        status = "okay";
 };
index 272ff61..d1375d3 100644 (file)
                        };
 
                        gpt: gpt@2098000 {
-                               compatible = "fsl,imx6sx-gpt", "fsl,imx31-gpt";
+                               compatible = "fsl,imx6sx-gpt", "fsl,imx6dl-gpt";
                                reg = <0x02098000 0x4000>;
                                interrupts = <GIC_SPI 55 IRQ_TYPE_LEVEL_HIGH>;
                                clocks = <&clks IMX6SX_CLK_GPT_BUS>,
index cbaf06f..eb91746 100644 (file)
@@ -36,8 +36,8 @@
                compatible = "gpio-fan";
                pinctrl-0 = <&pmx_fan_high_speed &pmx_fan_low_speed>;
                pinctrl-names = "default";
-               gpios = <&gpio1 14 GPIO_ACTIVE_LOW
-                        &gpio1 13 GPIO_ACTIVE_LOW>;
+               gpios = <&gpio1 14 GPIO_ACTIVE_HIGH
+                        &gpio1 13 GPIO_ACTIVE_HIGH>;
                gpio-fan,speed-map = <0    0
                                      3000 1
                                      6000 2>;
index e4645f6..2ab7486 100644 (file)
                        compatible = "amlogic,meson6-dwmac", "snps,dwmac";
                        reg = <0xc9410000 0x10000
                               0xc1108108 0x4>;
-                       interrupts = <GIC_SPI 8 IRQ_TYPE_EDGE_RISING>;
+                       interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
                        interrupt-names = "macirq";
                        status = "disabled";
                };
index 0872f6e..d50fc2f 100644 (file)
                cap-sd-highspeed;
                disable-wp;
 
-               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-               cd-inverted;
+               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
                vmmc-supply = <&vcc_3v3>;
        };
index 58669ab..0f0a46d 100644 (file)
                /* Realtek RTL8211F (0x001cc916) */
                eth_phy: ethernet-phy@0 {
                        reg = <0>;
-                       eee-broken-1000t;
                        interrupt-parent = <&gpio_intc>;
                        /* GPIOH_3 */
                        interrupts = <17 IRQ_TYPE_LEVEL_LOW>;
                cap-sd-highspeed;
                disable-wp;
 
-               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-               cd-inverted;
+               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
                vmmc-supply = <&tflash_vdd>;
                vqmmc-supply = <&tf_io>;
index f585361..6ac02be 100644 (file)
                cap-sd-highspeed;
                disable-wp;
 
-               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-               cd-inverted;
+               cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
                vmmc-supply = <&vcc_3v3>;
        };
index ddc7a7b..f57acf8 100644 (file)
                        interrupts-extended = <
                                &cpcap 15 0 &cpcap 14 0 &cpcap 28 0 &cpcap 19 0
                                &cpcap 18 0 &cpcap 17 0 &cpcap 16 0 &cpcap 49 0
-                               &cpcap 48 1
+                               &cpcap 48 0
                        >;
                        interrupt-names =
                                "id_ground", "id_float", "se0conn", "vbusvld",
index e53d326..93b4209 100644 (file)
 
        vdda-supply = <&vdac>;
 
-       #address-cells = <1>;
-       #size-cells = <0>;
-
        port {
-               reg = <0>;
                venc_out: endpoint {
                        remote-endpoint = <&opa_in>;
                        ti,channels = <1>;
index 182a539..826920e 100644 (file)
        /* For debugging, it is often good idea to remove this GPIO.
           It means you can remove back cover (to reboot by removing
           battery) and still use the MMC card. */
-       cd-gpios = <&gpio6 0 GPIO_ACTIVE_HIGH>; /* 160 */
+       cd-gpios = <&gpio6 0 GPIO_ACTIVE_LOW>; /* 160 */
 };
 
 /* most boards use vaux3, only some old versions use vmmc2 instead */
index 0d9b853..e142e6c 100644 (file)
                compatible = "ti,omap2-onenand";
                reg = <0 0 0x20000>;    /* CS0, offset 0, IO size 128K */
 
+               /*
+                * These timings are based on CONFIG_OMAP_GPMC_DEBUG=y reported
+                * bootloader set values when booted with v4.19 using both N950
+                * and N9 devices (OneNAND Manufacturer: Samsung):
+                *
+                *   gpmc cs0 before gpmc_cs_program_settings:
+                *   cs0 GPMC_CS_CONFIG1: 0xfd001202
+                *   cs0 GPMC_CS_CONFIG2: 0x00181800
+                *   cs0 GPMC_CS_CONFIG3: 0x00030300
+                *   cs0 GPMC_CS_CONFIG4: 0x18001804
+                *   cs0 GPMC_CS_CONFIG5: 0x03171d1d
+                *   cs0 GPMC_CS_CONFIG6: 0x97080000
+                */
                gpmc,sync-read;
                gpmc,sync-write;
                gpmc,burst-length = <16>;
                gpmc,device-width = <2>;
                gpmc,mux-add-data = <2>;
                gpmc,cs-on-ns = <0>;
-               gpmc,cs-rd-off-ns = <87>;
-               gpmc,cs-wr-off-ns = <87>;
+               gpmc,cs-rd-off-ns = <122>;
+               gpmc,cs-wr-off-ns = <122>;
                gpmc,adv-on-ns = <0>;
-               gpmc,adv-rd-off-ns = <10>;
-               gpmc,adv-wr-off-ns = <10>;
-               gpmc,oe-on-ns = <15>;
-               gpmc,oe-off-ns = <87>;
+               gpmc,adv-rd-off-ns = <15>;
+               gpmc,adv-wr-off-ns = <15>;
+               gpmc,oe-on-ns = <20>;
+               gpmc,oe-off-ns = <122>;
                gpmc,we-on-ns = <0>;
-               gpmc,we-off-ns = <87>;
-               gpmc,rd-cycle-ns = <112>;
-               gpmc,wr-cycle-ns = <112>;
-               gpmc,access-ns = <81>;
+               gpmc,we-off-ns = <122>;
+               gpmc,rd-cycle-ns = <148>;
+               gpmc,wr-cycle-ns = <148>;
+               gpmc,access-ns = <117>;
                gpmc,page-burst-access-ns = <15>;
                gpmc,bus-turnaround-ns = <0>;
                gpmc,cycle2cycle-delay-ns = <0>;
                gpmc,wait-monitoring-ns = <0>;
-               gpmc,clk-activation-ns = <5>;
-               gpmc,wr-data-mux-bus-ns = <30>;
-               gpmc,wr-access-ns = <81>;
-               gpmc,sync-clk-ps = <15000>;
+               gpmc,clk-activation-ns = <10>;
+               gpmc,wr-data-mux-bus-ns = <40>;
+               gpmc,wr-access-ns = <117>;
+
+               gpmc,sync-clk-ps = <15000>; /* TBC; Where this value came? */
 
                /*
                 * MTD partition table corresponding to Nokia's MeeGo 1.2
index 04758a2..67d77ee 100644 (file)
        };
 };
 
+/* Configure pwm clock source for timers 8 & 9 */
+&timer8 {
+       assigned-clocks = <&abe_clkctrl OMAP4_TIMER8_CLKCTRL 24>;
+       assigned-clock-parents = <&sys_clkin_ck>;
+};
+
+&timer9 {
+       assigned-clocks = <&l4_per_clkctrl OMAP4_TIMER9_CLKCTRL 24>;
+       assigned-clock-parents = <&sys_clkin_ck>;
+};
+
 /*
  * As uart1 is wired to mdm6600 with rts and cts, we can use the cts pin for
  * uart1 wakeirq.
index bc853eb..61a06f6 100644 (file)
 
        palmas_sys_nirq_pins: pinmux_palmas_sys_nirq_pins {
                pinctrl-single,pins = <
-                       OMAP5_IOPAD(0x068, PIN_INPUT_PULLUP | MUX_MODE0) /* sys_nirq1 */
+                       /* sys_nirq1 is pulled down as the SoC is inverting it for GIC */
+                       OMAP5_IOPAD(0x068, PIN_INPUT_PULLUP | MUX_MODE0)
                >;
        };
 
 
        palmas: palmas@48 {
                compatible = "ti,palmas";
-               interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */
+               /* sys_nirq/ext_sys_irq pins get inverted at mpuss wakeupgen */
+               interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_LOW>;
                reg = <0x48>;
                interrupt-controller;
                #interrupt-cells = <2>;
                pinctrl-names = "default";
                pinctrl-0 = <&twl6040_pins>;
 
-               interrupts = <GIC_SPI 119 IRQ_TYPE_NONE>; /* IRQ_SYS_2N cascaded to gic */
+               /* sys_nirq/ext_sys_irq pins get inverted at mpuss wakeupgen */
+               interrupts = <GIC_SPI 119 IRQ_TYPE_LEVEL_LOW>;
 
                /* audpwron gpio defined in the board specific dts */
 
index 5e21fb4..e78d371 100644 (file)
                        OMAP5_IOPAD(0x0042, PIN_INPUT_PULLDOWN | MUX_MODE6)  /* llib_wakereqin.gpio1_wk15 */
                >;
        };
+
+       palmas_sys_nirq_pins: pinmux_palmas_sys_nirq_pins {
+               pinctrl-single,pins = <
+                       /* sys_nirq1 is pulled down as the SoC is inverting it for GIC */
+                       OMAP5_IOPAD(0x068, PIN_INPUT_PULLUP | MUX_MODE0)
+               >;
+       };
 };
 
 &omap5_pmx_core {
 
        palmas: palmas@48 {
                compatible = "ti,palmas";
-               interrupts = <GIC_SPI 7 IRQ_TYPE_NONE>; /* IRQ_SYS_1N */
                reg = <0x48>;
+               pinctrl-0 = <&palmas_sys_nirq_pins>;
+               pinctrl-names = "default";
+               /* sys_nirq/ext_sys_irq pins get inverted at mpuss wakeupgen */
+               interrupts = <GIC_SPI 7 IRQ_TYPE_LEVEL_LOW>;
                interrupt-controller;
                #interrupt-cells = <2>;
                ti,system-power-controller;
index 9c7e309..0960348 100644 (file)
                                        <SYSC_IDLE_SMART>,
                                        <SYSC_IDLE_SMART_WKUP>;
                        ti,syss-mask = <1>;
-                       ti,no-reset-on-init;
-                       ti,no-idle-on-init;
                        /* Domains (V, P, C): core, core_pwrdm, l4per_clkdm */
                        clocks = <&l4per_clkctrl OMAP5_UART3_CLKCTRL 0>;
                        clock-names = "fck";
index 3cc33f7..3adc158 100644 (file)
 
                du: display@feb00000 {
                        compatible = "renesas,du-r8a7743";
-                       reg = <0 0xfeb00000 0 0x40000>,
-                             <0 0xfeb90000 0 0x1c>;
-                       reg-names = "du", "lvds.0";
+                       reg = <0 0xfeb00000 0 0x40000>;
                        interrupts = <GIC_SPI 256 IRQ_TYPE_LEVEL_HIGH>,
                                     <GIC_SPI 268 IRQ_TYPE_LEVEL_HIGH>;
                        clocks = <&cpg CPG_MOD 724>,
-                                <&cpg CPG_MOD 723>,
-                                <&cpg CPG_MOD 726>;
-                       clock-names = "du.0", "du.1", "lvds.0";
+                                <&cpg CPG_MOD 723>;
+                       clock-names = "du.0", "du.1";
                        status = "disabled";
 
                        ports {
                                port@1 {
                                        reg = <1>;
                                        du_out_lvds0: endpoint {
+                                               remote-endpoint = <&lvds0_in>;
+                                       };
+                               };
+                       };
+               };
+
+               lvds0: lvds@feb90000 {
+                       compatible = "renesas,r8a7743-lvds";
+                       reg = <0 0xfeb90000 0 0x1c>;
+                       clocks = <&cpg CPG_MOD 726>;
+                       power-domains = <&sysc R8A7743_PD_ALWAYS_ON>;
+                       resets = <&cpg 726>;
+                       status = "disabled";
+
+                       ports {
+                               #address-cells = <1>;
+                               #size-cells = <0>;
+
+                               port@0 {
+                                       reg = <0>;
+                                       lvds0_in: endpoint {
+                                               remote-endpoint = <&du_out_lvds0>;
+                                       };
+                               };
+                               port@1 {
+                                       reg = <1>;
+                                       lvds0_out: endpoint {
                                        };
                                };
                        };
index 4acb501..3ed4989 100644 (file)
                        pm_qos = <&qos_lcdc0>,
                                 <&qos_lcdc1>,
                                 <&qos_cif0>,
-                                <&qos_cif1>,
                                 <&qos_ipp>,
                                 <&qos_rga>;
                };
index 353d90f..13304b8 100644 (file)
                        #clock-cells = <0>;
                        compatible = "fixed-clock";
                        clock-frequency = <24000000>;
+                       clock-output-names = "osc24M";
                };
 
                osc32k: clk-32k {
index 5d23667..25540b7 100644 (file)
@@ -53,7 +53,7 @@
 
        aliases {
                serial0 = &uart0;
-               /* ethernet0 is the H3 emac, defined in sun8i-h3.dtsi */
+               ethernet0 = &emac;
                ethernet1 = &sdiowifi;
        };
 
index d5f11d6..bc85b6a 100644 (file)
                stdout-path = "serial0:115200n8";
        };
 
-       memory@80000000 {
+       /*
+        * Note that recent version of the device tree compiler (starting with
+        * version 1.4.2) warn about this node containing a reg property, but
+        * missing a unit-address. However, the bootloader on these Chromebook
+        * devices relies on the full name of this node to be exactly /memory.
+        * Adding the unit-address causes the bootloader to create a /memory
+        * node and write the memory bank configuration to that node, which in
+        * turn leads the kernel to believe that the device has 2 GiB of
+        * memory instead of the amount detected by the bootloader.
+        *
+        * The name of this node is effectively ABI and must not be changed.
+        */
+       memory {
+               device_type = "memory";
                reg = <0x0 0x80000000 0x0 0x80000000>;
        };
 
+       /delete-node/ memory@80000000;
+
        host1x@50000000 {
                hdmi@54280000 {
                        status = "okay";
index 689c893..b08d561 100644 (file)
        bus-num = <3>;
        status = "okay";
        spi-slave;
+       #address-cells = <0>;
 
-       slave@0 {
+       slave {
                compatible = "lwn,bk4";
                spi-max-frequency = <30000000>;
-               reg = <0>;
        };
 };
 
index c883fcb..46d4114 100644 (file)
@@ -25,7 +25,6 @@
 #ifndef __ASSEMBLY__
 struct irqaction;
 struct pt_regs;
-extern void migrate_irqs(void);
 
 extern void asm_do_IRQ(unsigned int, struct pt_regs *);
 void handle_IRQ(unsigned int, struct pt_regs *);
index ca56537..50e8986 100644 (file)
@@ -48,6 +48,7 @@
 #define KVM_REQ_SLEEP \
        KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
 #define KVM_REQ_IRQ_PENDING    KVM_ARCH_REQ(1)
+#define KVM_REQ_VCPU_RESET     KVM_ARCH_REQ(2)
 
 DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
 
@@ -147,6 +148,13 @@ struct kvm_cpu_context {
 
 typedef struct kvm_cpu_context kvm_cpu_context_t;
 
+struct vcpu_reset_state {
+       unsigned long   pc;
+       unsigned long   r0;
+       bool            be;
+       bool            reset;
+};
+
 struct kvm_vcpu_arch {
        struct kvm_cpu_context ctxt;
 
@@ -186,6 +194,8 @@ struct kvm_vcpu_arch {
        /* Cache some mmu pages needed inside spinlock regions */
        struct kvm_mmu_memory_cache mmu_page_cache;
 
+       struct vcpu_reset_state reset_state;
+
        /* Detect first run of a vcpu */
        bool has_run_once;
 };
index c4b1d4f..de20895 100644 (file)
@@ -76,4 +76,9 @@ static inline bool kvm_stage2_has_pud(struct kvm *kvm)
 #define S2_PMD_MASK                            PMD_MASK
 #define S2_PMD_SIZE                            PMD_SIZE
 
+static inline bool kvm_stage2_has_pmd(struct kvm *kvm)
+{
+       return true;
+}
+
 #endif /* __ARM_S2_PGTABLE_H_ */
index b3ef061..2c403e7 100644 (file)
@@ -1 +1,95 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ARM_XEN_PAGE_COHERENT_H
+#define _ASM_ARM_XEN_PAGE_COHERENT_H
+
+#include <linux/dma-mapping.h>
+#include <asm/page.h>
 #include <xen/arm/page-coherent.h>
+
+static inline const struct dma_map_ops *xen_get_dma_ops(struct device *dev)
+{
+       if (dev && dev->archdata.dev_dma_ops)
+               return dev->archdata.dev_dma_ops;
+       return get_arch_dma_ops(NULL);
+}
+
+static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
+               dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs)
+{
+       return xen_get_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs);
+}
+
+static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
+               void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs)
+{
+       xen_get_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs);
+}
+
+static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
+            dma_addr_t dev_addr, unsigned long offset, size_t size,
+            enum dma_data_direction dir, unsigned long attrs)
+{
+       unsigned long page_pfn = page_to_xen_pfn(page);
+       unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
+       unsigned long compound_pages =
+               (1<<compound_order(page)) * XEN_PFN_PER_PAGE;
+       bool local = (page_pfn <= dev_pfn) &&
+               (dev_pfn - page_pfn < compound_pages);
+
+       /*
+        * Dom0 is mapped 1:1, while the Linux page can span across
+        * multiple Xen pages, it's not possible for it to contain a
+        * mix of local and foreign Xen pages. So if the first xen_pfn
+        * == mfn the page is local otherwise it's a foreign page
+        * grant-mapped in dom0. If the page is local we can safely
+        * call the native dma_ops function, otherwise we call the xen
+        * specific function.
+        */
+       if (local)
+               xen_get_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
+       else
+               __xen_dma_map_page(hwdev, page, dev_addr, offset, size, dir, attrs);
+}
+
+static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
+               size_t size, enum dma_data_direction dir, unsigned long attrs)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+       /*
+        * Dom0 is mapped 1:1, while the Linux page can be spanned accross
+        * multiple Xen page, it's not possible to have a mix of local and
+        * foreign Xen page. Dom0 is mapped 1:1, so calling pfn_valid on a
+        * foreign mfn will always return false. If the page is local we can
+        * safely call the native dma_ops function, otherwise we call the xen
+        * specific function.
+        */
+       if (pfn_valid(pfn)) {
+               if (xen_get_dma_ops(hwdev)->unmap_page)
+                       xen_get_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
+       } else
+               __xen_dma_unmap_page(hwdev, handle, size, dir, attrs);
+}
+
+static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+       if (pfn_valid(pfn)) {
+               if (xen_get_dma_ops(hwdev)->sync_single_for_cpu)
+                       xen_get_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
+       } else
+               __xen_dma_sync_single_for_cpu(hwdev, handle, size, dir);
+}
+
+static inline void xen_dma_sync_single_for_device(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+       if (pfn_valid(pfn)) {
+               if (xen_get_dma_ops(hwdev)->sync_single_for_device)
+                       xen_get_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
+       } else
+               __xen_dma_sync_single_for_device(hwdev, handle, size, dir);
+}
+
+#endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */
index 9908dac..8448613 100644 (file)
@@ -31,7 +31,6 @@
 #include <linux/smp.h>
 #include <linux/init.h>
 #include <linux/seq_file.h>
-#include <linux/ratelimit.h>
 #include <linux/errno.h>
 #include <linux/list.h>
 #include <linux/kallsyms.h>
@@ -109,64 +108,3 @@ int __init arch_probe_nr_irqs(void)
        return nr_irqs;
 }
 #endif
-
-#ifdef CONFIG_HOTPLUG_CPU
-static bool migrate_one_irq(struct irq_desc *desc)
-{
-       struct irq_data *d = irq_desc_get_irq_data(desc);
-       const struct cpumask *affinity = irq_data_get_affinity_mask(d);
-       struct irq_chip *c;
-       bool ret = false;
-
-       /*
-        * If this is a per-CPU interrupt, or the affinity does not
-        * include this CPU, then we have nothing to do.
-        */
-       if (irqd_is_per_cpu(d) || !cpumask_test_cpu(smp_processor_id(), affinity))
-               return false;
-
-       if (cpumask_any_and(affinity, cpu_online_mask) >= nr_cpu_ids) {
-               affinity = cpu_online_mask;
-               ret = true;
-       }
-
-       c = irq_data_get_irq_chip(d);
-       if (!c->irq_set_affinity)
-               pr_debug("IRQ%u: unable to set affinity\n", d->irq);
-       else if (c->irq_set_affinity(d, affinity, false) == IRQ_SET_MASK_OK && ret)
-               cpumask_copy(irq_data_get_affinity_mask(d), affinity);
-
-       return ret;
-}
-
-/*
- * The current CPU has been marked offline.  Migrate IRQs off this CPU.
- * If the affinity settings do not allow other CPUs, force them onto any
- * available CPU.
- *
- * Note: we must iterate over all IRQs, whether they have an attached
- * action structure or not, as we need to get chained interrupts too.
- */
-void migrate_irqs(void)
-{
-       unsigned int i;
-       struct irq_desc *desc;
-       unsigned long flags;
-
-       local_irq_save(flags);
-
-       for_each_irq_desc(i, desc) {
-               bool affinity_broken;
-
-               raw_spin_lock(&desc->lock);
-               affinity_broken = migrate_one_irq(desc);
-               raw_spin_unlock(&desc->lock);
-
-               if (affinity_broken)
-                       pr_warn_ratelimited("IRQ%u no longer affine to CPU%u\n",
-                               i, smp_processor_id());
-       }
-
-       local_irq_restore(flags);
-}
-#endif /* CONFIG_HOTPLUG_CPU */
index 3bf8223..1d6f5ea 100644 (file)
@@ -254,7 +254,7 @@ int __cpu_disable(void)
        /*
         * OK - migrate IRQs away from this CPU
         */
-       migrate_irqs();
+       irq_migrate_all_off_this_cpu();
 
        /*
         * Flush user cache and TLB mappings, and then remove this CPU
index 222c163..e8bd288 100644 (file)
@@ -1450,6 +1450,6 @@ void kvm_reset_coprocs(struct kvm_vcpu *vcpu)
        reset_coproc_regs(vcpu, table, num);
 
        for (num = 1; num < NR_CP15_REGS; num++)
-               if (vcpu_cp15(vcpu, num) == 0x42424242)
-                       panic("Didn't reset vcpu_cp15(vcpu, %zi)", num);
+               WARN(vcpu_cp15(vcpu, num) == 0x42424242,
+                    "Didn't reset vcpu_cp15(vcpu, %zi)", num);
 }
index 5ed0c3e..e533279 100644 (file)
@@ -26,6 +26,7 @@
 #include <asm/cputype.h>
 #include <asm/kvm_arm.h>
 #include <asm/kvm_coproc.h>
+#include <asm/kvm_emulate.h>
 
 #include <kvm/arm_arch_timer.h>
 
@@ -69,6 +70,29 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
        /* Reset CP15 registers */
        kvm_reset_coprocs(vcpu);
 
+       /*
+        * Additional reset state handling that PSCI may have imposed on us.
+        * Must be done after all the sys_reg reset.
+        */
+       if (READ_ONCE(vcpu->arch.reset_state.reset)) {
+               unsigned long target_pc = vcpu->arch.reset_state.pc;
+
+               /* Gracefully handle Thumb2 entry point */
+               if (target_pc & 1) {
+                       target_pc &= ~1UL;
+                       vcpu_set_thumb(vcpu);
+               }
+
+               /* Propagate caller endianness */
+               if (vcpu->arch.reset_state.be)
+                       kvm_vcpu_set_be(vcpu);
+
+               *vcpu_pc(vcpu) = target_pc;
+               vcpu_set_reg(vcpu, 0, vcpu->arch.reset_state.r0);
+
+               vcpu->arch.reset_state.reset = false;
+       }
+
        /* Reset arch_timer context */
        return kvm_timer_vcpu_reset(vcpu);
 }
index 318394e..95a11d5 100644 (file)
@@ -83,7 +83,7 @@ static void __iomem *cns3xxx_pci_map_bus(struct pci_bus *bus,
        } else /* remote PCI bus */
                base = cnspci->cfg1_regs + ((busno & 0xf) << 20);
 
-       return base + (where & 0xffc) + (devfn << 12);
+       return base + where + (devfn << 12);
 }
 
 static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
@@ -93,7 +93,7 @@ static int cns3xxx_pci_read_config(struct pci_bus *bus, unsigned int devfn,
        u32 mask = (0x1ull << (size * 8)) - 1;
        int shift = (where % 4) * 8;
 
-       ret = pci_generic_config_read32(bus, devfn, where, size, val);
+       ret = pci_generic_config_read(bus, devfn, where, size, val);
 
        if (ret == PCIBIOS_SUCCESSFUL && !bus->number && !devfn &&
            (where & 0xffc) == PCI_CLASS_REVISION)
index e52ec16..c4da635 100644 (file)
@@ -208,9 +208,9 @@ static struct gpiod_lookup_table mmc_gpios_table = {
        .dev_id = "da830-mmc.0",
        .table = {
                /* gpio chip 1 contains gpio range 32-63 */
-               GPIO_LOOKUP("davinci_gpio.0", DA830_MMCSD_CD_PIN, "cd",
+               GPIO_LOOKUP("davinci_gpio", DA830_MMCSD_CD_PIN, "cd",
                            GPIO_ACTIVE_LOW),
-               GPIO_LOOKUP("davinci_gpio.0", DA830_MMCSD_WP_PIN, "wp",
+               GPIO_LOOKUP("davinci_gpio", DA830_MMCSD_WP_PIN, "wp",
                            GPIO_ACTIVE_LOW),
        },
 };
index 6a29baf..44bca04 100644 (file)
@@ -805,9 +805,9 @@ static struct gpiod_lookup_table mmc_gpios_table = {
        .dev_id = "da830-mmc.0",
        .table = {
                /* gpio chip 2 contains gpio range 64-95 */
-               GPIO_LOOKUP("davinci_gpio.0", DA850_MMCSD_CD_PIN, "cd",
+               GPIO_LOOKUP("davinci_gpio", DA850_MMCSD_CD_PIN, "cd",
                            GPIO_ACTIVE_LOW),
-               GPIO_LOOKUP("davinci_gpio.0", DA850_MMCSD_WP_PIN, "wp",
+               GPIO_LOOKUP("davinci_gpio", DA850_MMCSD_WP_PIN, "wp",
                            GPIO_ACTIVE_HIGH),
        },
 };
index f53a461..f7fa960 100644 (file)
@@ -117,9 +117,9 @@ static struct platform_device davinci_nand_device = {
 static struct gpiod_lookup_table i2c_recovery_gpiod_table = {
        .dev_id = "i2c_davinci.1",
        .table = {
-               GPIO_LOOKUP("davinci_gpio.0", DM355_I2C_SDA_PIN, "sda",
+               GPIO_LOOKUP("davinci_gpio", DM355_I2C_SDA_PIN, "sda",
                            GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
-               GPIO_LOOKUP("davinci_gpio.0", DM355_I2C_SCL_PIN, "scl",
+               GPIO_LOOKUP("davinci_gpio", DM355_I2C_SCL_PIN, "scl",
                            GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
        },
 };
index e142811..b80c4ee 100644 (file)
@@ -660,9 +660,9 @@ static struct i2c_board_info __initdata i2c_info[] =  {
 static struct gpiod_lookup_table i2c_recovery_gpiod_table = {
        .dev_id = "i2c_davinci.1",
        .table = {
-               GPIO_LOOKUP("davinci_gpio.0", DM644X_I2C_SDA_PIN, "sda",
+               GPIO_LOOKUP("davinci_gpio", DM644X_I2C_SDA_PIN, "sda",
                            GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
-               GPIO_LOOKUP("davinci_gpio.0", DM644X_I2C_SCL_PIN, "scl",
+               GPIO_LOOKUP("davinci_gpio", DM644X_I2C_SCL_PIN, "scl",
                            GPIO_ACTIVE_HIGH | GPIO_OPEN_DRAIN),
        },
 };
index 8e8d51f..94c4f12 100644 (file)
@@ -134,9 +134,9 @@ static const short hawk_mmcsd0_pins[] = {
 static struct gpiod_lookup_table mmc_gpios_table = {
        .dev_id = "da830-mmc.0",
        .table = {
-               GPIO_LOOKUP("davinci_gpio.0", DA850_HAWK_MMCSD_CD_PIN, "cd",
+               GPIO_LOOKUP("davinci_gpio", DA850_HAWK_MMCSD_CD_PIN, "cd",
                            GPIO_ACTIVE_LOW),
-               GPIO_LOOKUP("davinci_gpio.0", DA850_HAWK_MMCSD_WP_PIN, "wp",
+               GPIO_LOOKUP("davinci_gpio", DA850_HAWK_MMCSD_WP_PIN, "wp",
                            GPIO_ACTIVE_LOW),
        },
 };
index a109f64..8dfad01 100644 (file)
@@ -390,10 +390,14 @@ static int __ref impd1_probe(struct lm_device *dev)
                        char *mmciname;
 
                        lookup = devm_kzalloc(&dev->dev,
-                                             sizeof(*lookup) + 3 * sizeof(struct gpiod_lookup),
+                                             struct_size(lookup, table, 3),
                                              GFP_KERNEL);
                        chipname = devm_kstrdup(&dev->dev, devname, GFP_KERNEL);
-                       mmciname = kasprintf(GFP_KERNEL, "lm%x:00700", dev->id);
+                       mmciname = devm_kasprintf(&dev->dev, GFP_KERNEL,
+                                                 "lm%x:00700", dev->id);
+                       if (!lookup || !chipname || !mmciname)
+                               return -ENOMEM;
+
                        lookup->dev_id = mmciname;
                        /*
                         * Offsets on GPIO block 1:
index 3b73813..23e8c93 100644 (file)
@@ -75,8 +75,7 @@ void __init n2100_map_io(void)
 /*
  * N2100 PCI.
  */
-static int __init
-n2100_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
+static int n2100_pci_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
 {
        int irq;
 
index a8b291f..dae514c 100644 (file)
@@ -152,6 +152,10 @@ static int omap_enter_idle_coupled(struct cpuidle_device *dev,
        mpuss_can_lose_context = (cx->mpu_state == PWRDM_POWER_RET) &&
                                 (cx->mpu_logic_state == PWRDM_POWER_OFF);
 
+       /* Enter broadcast mode for periodic timers */
+       tick_broadcast_enable();
+
+       /* Enter broadcast mode for one-shot timers */
        tick_broadcast_enter();
 
        /*
@@ -218,15 +222,6 @@ fail:
        return index;
 }
 
-/*
- * For each cpu, setup the broadcast timer because local timers
- * stops for the states above C1.
- */
-static void omap_setup_broadcast_timer(void *arg)
-{
-       tick_broadcast_enable();
-}
-
 static struct cpuidle_driver omap4_idle_driver = {
        .name                           = "omap4_idle",
        .owner                          = THIS_MODULE,
@@ -319,8 +314,5 @@ int __init omap4_idle_init(void)
        if (!cpu_clkdm[0] || !cpu_clkdm[1])
                return -ENODEV;
 
-       /* Configure the broadcast timer on each cpu */
-       on_each_cpu(omap_setup_broadcast_timer, NULL, 1);
-
        return cpuidle_register(idle_driver, cpu_online_mask);
 }
index f86b72d..1444b4b 100644 (file)
@@ -83,6 +83,7 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
        u32 enable_mask, enable_shift;
        u32 pipd_mask, pipd_shift;
        u32 reg;
+       int ret;
 
        if (dsi_id == 0) {
                enable_mask = OMAP4_DSI1_LANEENABLE_MASK;
@@ -98,7 +99,11 @@ static int omap4_dsi_mux_pads(int dsi_id, unsigned lanes)
                return -ENODEV;
        }
 
-       regmap_read(omap4_dsi_mux_syscon, OMAP4_DSIPHY_SYSCON_OFFSET, &reg);
+       ret = regmap_read(omap4_dsi_mux_syscon,
+                                         OMAP4_DSIPHY_SYSCON_OFFSET,
+                                         &reg);
+       if (ret)
+               return ret;
 
        reg &= ~enable_mask;
        reg &= ~pipd_mask;
index fc5fb77..17558be 100644 (file)
@@ -50,6 +50,9 @@
 #define OMAP4_NR_BANKS         4
 #define OMAP4_NR_IRQS          128
 
+#define SYS_NIRQ1_EXT_SYS_IRQ_1        7
+#define SYS_NIRQ2_EXT_SYS_IRQ_2        119
+
 static void __iomem *wakeupgen_base;
 static void __iomem *sar_base;
 static DEFINE_RAW_SPINLOCK(wakeupgen_lock);
@@ -153,6 +156,37 @@ static void wakeupgen_unmask(struct irq_data *d)
        irq_chip_unmask_parent(d);
 }
 
+/*
+ * The sys_nirq pins bypass peripheral modules and are wired directly
+ * to MPUSS wakeupgen. They get automatically inverted for GIC.
+ */
+static int wakeupgen_irq_set_type(struct irq_data *d, unsigned int type)
+{
+       bool inverted = false;
+
+       switch (type) {
+       case IRQ_TYPE_LEVEL_LOW:
+               type &= ~IRQ_TYPE_LEVEL_MASK;
+               type |= IRQ_TYPE_LEVEL_HIGH;
+               inverted = true;
+               break;
+       case IRQ_TYPE_EDGE_FALLING:
+               type &= ~IRQ_TYPE_EDGE_BOTH;
+               type |= IRQ_TYPE_EDGE_RISING;
+               inverted = true;
+               break;
+       default:
+               break;
+       }
+
+       if (inverted && d->hwirq != SYS_NIRQ1_EXT_SYS_IRQ_1 &&
+           d->hwirq != SYS_NIRQ2_EXT_SYS_IRQ_2)
+               pr_warn("wakeupgen: irq%li polarity inverted in dts\n",
+                       d->hwirq);
+
+       return irq_chip_set_type_parent(d, type);
+}
+
 #ifdef CONFIG_HOTPLUG_CPU
 static DEFINE_PER_CPU(u32 [MAX_NR_REG_BANKS], irqmasks);
 
@@ -446,7 +480,7 @@ static struct irq_chip wakeupgen_chip = {
        .irq_mask               = wakeupgen_mask,
        .irq_unmask             = wakeupgen_unmask,
        .irq_retrigger          = irq_chip_retrigger_hierarchy,
-       .irq_set_type           = irq_chip_set_type_parent,
+       .irq_set_type           = wakeupgen_irq_set_type,
        .flags                  = IRQCHIP_SKIP_SET_WAKE | IRQCHIP_MASK_ON_SUSPEND,
 #ifdef CONFIG_SMP
        .irq_set_affinity       = irq_chip_set_affinity_parent,
index b5531dd..3a04c73 100644 (file)
@@ -1002,8 +1002,10 @@ static int _enable_clocks(struct omap_hwmod *oh)
                clk_enable(oh->_clk);
 
        list_for_each_entry(os, &oh->slave_ports, node) {
-               if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE))
+               if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE)) {
+                       omap2_clk_deny_idle(os->_clk);
                        clk_enable(os->_clk);
+               }
        }
 
        /* The opt clocks are controlled by the device driver. */
@@ -1055,8 +1057,10 @@ static int _disable_clocks(struct omap_hwmod *oh)
                clk_disable(oh->_clk);
 
        list_for_each_entry(os, &oh->slave_ports, node) {
-               if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE))
+               if (os->_clk && (os->flags & OCPIF_SWSUP_IDLE)) {
                        clk_disable(os->_clk);
+                       omap2_clk_allow_idle(os->_clk);
+               }
        }
 
        if (oh->flags & HWMOD_OPT_CLKS_NEEDED)
@@ -2436,9 +2440,13 @@ static void _setup_iclk_autoidle(struct omap_hwmod *oh)
                        continue;
 
                if (os->flags & OCPIF_SWSUP_IDLE) {
-                       /* XXX omap_iclk_deny_idle(c); */
+                       /*
+                        * we might have multiple users of one iclk with
+                        * different requirements, disable autoidle when
+                        * the module is enabled, e.g. dss iclk
+                        */
                } else {
-                       /* XXX omap_iclk_allow_idle(c); */
+                       /* we are enabling autoidle afterwards anyways */
                        clk_enable(os->_clk);
                }
        }
index 5fb6f79..afd9897 100644 (file)
@@ -32,6 +32,8 @@ void __iomem *rst_manager_base_addr;
 void __iomem *sdr_ctl_base_addr;
 unsigned long socfpga_cpu1start_addr;
 
+extern void __init socfpga_reset_init(void);
+
 static void __init socfpga_sysmgr_init(void)
 {
        struct device_node *np;
@@ -64,6 +66,7 @@ static void __init socfpga_init_irq(void)
 
        if (IS_ENABLED(CONFIG_EDAC_ALTERA_OCRAM))
                socfpga_init_ocram_ecc();
+       socfpga_reset_init();
 }
 
 static void __init socfpga_arria10_init_irq(void)
@@ -74,6 +77,7 @@ static void __init socfpga_arria10_init_irq(void)
                socfpga_init_arria10_l2_ecc();
        if (IS_ENABLED(CONFIG_EDAC_ALTERA_OCRAM))
                socfpga_init_arria10_ocram_ecc();
+       socfpga_reset_init();
 }
 
 static void socfpga_cyclone5_restart(enum reboot_mode mode, const char *cmd)
index 028e50c..a32c3b6 100644 (file)
@@ -3,6 +3,7 @@
 #include <linux/suspend.h>
 #include <asm/suspend.h>
 #include "smc.h"
+#include "pm.h"
 
 static int tango_pm_powerdown(unsigned long arg)
 {
@@ -24,10 +25,7 @@ static const struct platform_suspend_ops tango_pm_ops = {
        .valid = suspend_valid_only_mem,
 };
 
-static int __init tango_pm_init(void)
+void __init tango_pm_init(void)
 {
        suspend_set_ops(&tango_pm_ops);
-       return 0;
 }
-
-late_initcall(tango_pm_init);
diff --git a/arch/arm/mach-tango/pm.h b/arch/arm/mach-tango/pm.h
new file mode 100644 (file)
index 0000000..35ea705
--- /dev/null
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#ifdef CONFIG_SUSPEND
+void __init tango_pm_init(void);
+#else
+#define tango_pm_init NULL
+#endif
index 677dd7b..824f907 100644 (file)
@@ -2,6 +2,7 @@
 #include <asm/mach/arch.h>
 #include <asm/hardware/cache-l2x0.h>
 #include "smc.h"
+#include "pm.h"
 
 static void tango_l2c_write(unsigned long val, unsigned int reg)
 {
@@ -15,4 +16,5 @@ DT_MACHINE_START(TANGO_DT, "Sigma Tango DT")
        .dt_compat      = tango_dt_compat,
        .l2c_aux_mask   = ~0,
        .l2c_write_sec  = tango_l2c_write,
+       .init_late      = tango_pm_init,
 MACHINE_END
index f1e2922..1e3e08a 100644 (file)
@@ -2390,4 +2390,6 @@ void arch_teardown_dma_ops(struct device *dev)
                return;
 
        arm_teardown_iommu_dma_ops(dev);
+       /* Let arch_setup_dma_ops() start again from scratch upon re-probe */
+       set_dma_ops(dev, NULL);
 }
index ed36dca..f519199 100644 (file)
@@ -190,8 +190,6 @@ static int pxa_ssp_remove(struct platform_device *pdev)
        if (ssp == NULL)
                return -ENODEV;
 
-       iounmap(ssp->mmio_base);
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        release_mem_region(res->start, resource_size(res));
 
@@ -201,7 +199,6 @@ static int pxa_ssp_remove(struct platform_device *pdev)
        list_del(&ssp->node);
        mutex_unlock(&ssp_lock);
 
-       kfree(ssp);
        return 0;
 }
 
index 2c118a6..0dc23fc 100644 (file)
@@ -247,7 +247,7 @@ int arch_prepare_optimized_kprobe(struct optimized_kprobe *op, struct kprobe *or
        }
 
        /* Copy arch-dep-instance from template. */
-       memcpy(code, (unsigned char *)optprobe_template_entry,
+       memcpy(code, (unsigned long *)&optprobe_template_entry,
                        TMPL_END_IDX * sizeof(kprobe_opcode_t));
 
        /* Adjust buffer according to instruction. */
index cb44aa2..e1d44b9 100644 (file)
@@ -7,7 +7,6 @@
 #include <linux/of_address.h>
 #include <linux/slab.h>
 #include <linux/types.h>
-#include <linux/dma-mapping.h>
 #include <linux/vmalloc.h>
 #include <linux/swiotlb.h>
 
index b0c64f7..8974b5a 100644 (file)
                reg = <0x3a3>;
                interrupt-parent = <&r_intc>;
                interrupts = <0 IRQ_TYPE_LEVEL_LOW>;
+               x-powers,drive-vbus-en; /* set N_VBUSEN as output pin */
        };
 };
 
index 837a03d..2abb335 100644 (file)
                };
 
                video-codec@1c0e000 {
-                       compatible = "allwinner,sun50i-h5-video-engine";
+                       compatible = "allwinner,sun50i-a64-video-engine";
                        reg = <0x01c0e000 0x1000>;
                        clocks = <&ccu CLK_BUS_VE>, <&ccu CLK_VE>,
                                 <&ccu CLK_DRAM_VE>;
index e14e0ce..016641a 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
index 8cd50b7..ade2ee0 100644 (file)
        max-frequency = <200000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddio_ao3v3>;
        vqmmc-supply = <&vddio_tf>;
index 4cf7f6e..25105ac 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_card>;
index 2e1cd5e..1cc9dc6 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&tflash_vdd>;
        vqmmc-supply = <&tf_io>;
index ce86226..0be0f2a 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_card>;
index 93a4acf..ad4d50b 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vcc_3v3>;
 };
index ec09bb5..2d2db78 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vcc_3v3>;
index f1c410e..796baea 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_card>;
index db29344..255cede 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vcc_3v3>;
        vqmmc-supply = <&vcc_card>;
index 6739697..9cbdb85 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_card>;
index a1b3101..bc811a2 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
index 3c3a667..3f086ed 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
index f7a1cff..8acfd40 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
index 7212dc4..7fa20a8 100644 (file)
        max-frequency = <100000000>;
        disable-wp;
 
-       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_HIGH>;
-       cd-inverted;
+       cd-gpios = <&gpio CARD_6 GPIO_ACTIVE_LOW>;
 
        vmmc-supply = <&vddao_3v3>;
        vqmmc-supply = <&vddio_boot>;
index 64acccc..f74b13a 100644 (file)
 
        pinctrl_usdhc1_100mhz: usdhc1-100grp {
                fsl,pins = <
-                       MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK                 0x85
-                       MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                 0xc5
-                       MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6             0xc5
-                       MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7             0xc5
-                       MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE           0x85
+                       MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK                 0x8d
+                       MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                 0xcd
+                       MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6             0xcd
+                       MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7             0xcd
+                       MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE           0x8d
                        MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B         0xc1
                >;
        };
 
        pinctrl_usdhc1_200mhz: usdhc1-200grp {
                fsl,pins = <
-                       MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK                 0x87
-                       MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                 0xc7
-                       MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6             0xc7
-                       MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7             0xc7
-                       MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE           0x87
+                       MX8MQ_IOMUXC_SD1_CLK_USDHC1_CLK                 0x9f
+                       MX8MQ_IOMUXC_SD1_CMD_USDHC1_CMD                 0xdf
+                       MX8MQ_IOMUXC_SD1_DATA0_USDHC1_DATA0             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA1_USDHC1_DATA1             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA2_USDHC1_DATA2             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA3_USDHC1_DATA3             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA4_USDHC1_DATA4             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA5_USDHC1_DATA5             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA6_USDHC1_DATA6             0xdf
+                       MX8MQ_IOMUXC_SD1_DATA7_USDHC1_DATA7             0xdf
+                       MX8MQ_IOMUXC_SD1_STROBE_USDHC1_STROBE           0x9f
                        MX8MQ_IOMUXC_SD1_RESET_B_USDHC1_RESET_B         0xc1
                >;
        };
index 8e9d6d5..b6d3149 100644 (file)
                                         <&clk IMX8MQ_CLK_NAND_USDHC_BUS>,
                                         <&clk IMX8MQ_CLK_USDHC1_ROOT>;
                                clock-names = "ipg", "ahb", "per";
+                               assigned-clocks = <&clk IMX8MQ_CLK_USDHC1>;
+                               assigned-clock-rates = <400000000>;
                                fsl,tuning-start-tap = <20>;
                                fsl,tuning-step = <2>;
                                bus-width = <4>;
index 5b4a960..2468762 100644 (file)
                reg = <0>;
                pinctrl-names = "default";
                pinctrl-0 = <&cp0_copper_eth_phy_reset>;
-               reset-gpios = <&cp1_gpio1 11 GPIO_ACTIVE_LOW>;
+               reset-gpios = <&cp0_gpio2 11 GPIO_ACTIVE_LOW>;
                reset-assert-us = <10000>;
        };
 
index 29ea7e8..329f8ce 100644 (file)
        pinctrl-0 = <&cp0_pcie_pins>;
        num-lanes = <4>;
        num-viewport = <8>;
-       reset-gpio = <&cp0_gpio1 20 GPIO_ACTIVE_LOW>;
+       reset-gpios = <&cp0_gpio2 20 GPIO_ACTIVE_LOW>;
        status = "okay";
 };
 
index 7d94c1f..7f799cb 100644 (file)
                method = "smc";
        };
 
+       reserved-memory {
+               #address-cells = <2>;
+               #size-cells = <2>;
+               ranges;
+
+               /*
+                * This area matches the mapping done with a
+                * mainline U-Boot, and should be updated by the
+                * bootloader.
+                */
+
+               psci-area@4000000 {
+                       reg = <0x0 0x4000000 0x0 0x200000>;
+                       no-map;
+               };
+       };
+
        ap806 {
                #address-cells = <2>;
                #size-cells = <2>;
index 99b7495..838e32c 100644 (file)
                };
 
                intc: interrupt-controller@9bc0000 {
-                       compatible = "arm,gic-v3";
+                       compatible = "qcom,msm8996-gic-v3", "arm,gic-v3";
                        #interrupt-cells = <3>;
                        interrupt-controller;
                        #redistributor-regions = <1>;
index 20745a8..719ed9d 100644 (file)
                                 <&cpg CPG_CORE R8A774A1_CLK_S3D1>,
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x13>, <&dmac1 0x12>,
+                              <&dmac2 0x13>, <&dmac2 0x12>;
+                       dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A774A1_PD_ALWAYS_ON>;
                        resets = <&cpg 310>;
                        status = "disabled";
index afedbf5..0648d12 100644 (file)
                                 <&cpg CPG_CORE R8A7796_CLK_S3D1>,
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x13>, <&dmac1 0x12>,
+                              <&dmac2 0x13>, <&dmac2 0x12>;
+                       dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A7796_PD_ALWAYS_ON>;
                        resets = <&cpg 310>;
                        status = "disabled";
index 6dc9b1f..4b3730f 100644 (file)
                                 <&cpg CPG_CORE R8A77965_CLK_S3D1>,
                                 <&scif_clk>;
                        clock-names = "fck", "brg_int", "scif_clk";
+                       dmas = <&dmac1 0x13>, <&dmac1 0x12>,
+                              <&dmac2 0x13>, <&dmac2 0x12>;
+                       dma-names = "tx", "rx", "tx", "rx";
                        power-domains = <&sysc R8A77965_PD_ALWAYS_ON>;
                        resets = <&cpg 310>;
                        status = "disabled";
index bd937d6..040b36e 100644 (file)
@@ -40,6 +40,7 @@
                pinctrl-0 = <&usb30_host_drv>;
                regulator-name = "vcc_host_5v";
                regulator-always-on;
+               regulator-boot-on;
                vin-supply = <&vcc_sys>;
        };
 
@@ -51,6 +52,7 @@
                pinctrl-0 = <&usb20_host_drv>;
                regulator-name = "vcc_host1_5v";
                regulator-always-on;
+               regulator-boot-on;
                vin-supply = <&vcc_sys>;
        };
 
index 1ee0dc0..d1cf404 100644 (file)
@@ -22,7 +22,7 @@
                backlight = <&backlight>;
                power-supply = <&pp3300_disp>;
 
-               ports {
+               port {
                        panel_in_edp: endpoint {
                                remote-endpoint = <&edp_out_panel>;
                        };
index 81e7310..15e254a 100644 (file)
@@ -43,7 +43,7 @@
                backlight = <&backlight>;
                power-supply = <&pp3300_disp>;
 
-               ports {
+               port {
                        panel_in_edp: endpoint {
                                remote-endpoint = <&edp_out_panel>;
                        };
index 0b8f1ed..b48a63c 100644 (file)
@@ -91,7 +91,7 @@
                pinctrl-0 = <&lcd_panel_reset>;
                power-supply = <&vcc3v3_s0>;
 
-               ports {
+               port {
                        panel_in_edp: endpoint {
                                remote-endpoint = <&edp_out_panel>;
                        };
index 3ef443c..c8432e2 100644 (file)
@@ -506,11 +506,15 @@ CONFIG_SND_SOC_ROCKCHIP=m
 CONFIG_SND_SOC_ROCKCHIP_SPDIF=m
 CONFIG_SND_SOC_ROCKCHIP_RT5645=m
 CONFIG_SND_SOC_RK3399_GRU_SOUND=m
+CONFIG_SND_MESON_AXG_SOUND_CARD=m
 CONFIG_SND_SOC_SAMSUNG=y
 CONFIG_SND_SOC_RCAR=m
 CONFIG_SND_SOC_AK4613=m
 CONFIG_SND_SIMPLE_CARD=m
 CONFIG_SND_AUDIO_GRAPH_CARD=m
+CONFIG_SND_SOC_ES7134=m
+CONFIG_SND_SOC_ES7241=m
+CONFIG_SND_SOC_TAS571X=m
 CONFIG_I2C_HID=m
 CONFIG_USB=y
 CONFIG_USB_OTG=y
index 2173ad3..1c9a3a0 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef __ASM_PROTOTYPES_H
 #define __ASM_PROTOTYPES_H
 /*
- * CONFIG_MODEVERIONS requires a C declaration to generate the appropriate CRC
+ * CONFIG_MODVERSIONS requires a C declaration to generate the appropriate CRC
  * for each symbol. Since commit:
  *
  *   4efca4ed05cbdfd1 ("kbuild: modversions for EXPORT_SYMBOL() for asm")
index 13dd42c..926434f 100644 (file)
  */
 #define ARCH_DMA_MINALIGN      (128)
 
+#ifdef CONFIG_KASAN_SW_TAGS
+#define ARCH_SLAB_MINALIGN     (1ULL << KASAN_SHADOW_SCALE_SHIFT)
+#endif
+
 #ifndef __ASSEMBLY__
 
 #include <linux/bitops.h>
index 3dd3d66..4658c93 100644 (file)
@@ -20,9 +20,6 @@ struct dev_archdata {
 #ifdef CONFIG_IOMMU_API
        void *iommu;                    /* private IOMMU data */
 #endif
-#ifdef CONFIG_XEN
-       const struct dma_map_ops *dev_dma_ops;
-#endif
 };
 
 struct pdev_archdata {
index 7732d0b..da3fc73 100644 (file)
@@ -48,6 +48,7 @@
 #define KVM_REQ_SLEEP \
        KVM_ARCH_REQ_FLAGS(0, KVM_REQUEST_WAIT | KVM_REQUEST_NO_WAKEUP)
 #define KVM_REQ_IRQ_PENDING    KVM_ARCH_REQ(1)
+#define KVM_REQ_VCPU_RESET     KVM_ARCH_REQ(2)
 
 DECLARE_STATIC_KEY_FALSE(userspace_irqchip_in_use);
 
@@ -208,6 +209,13 @@ struct kvm_cpu_context {
 
 typedef struct kvm_cpu_context kvm_cpu_context_t;
 
+struct vcpu_reset_state {
+       unsigned long   pc;
+       unsigned long   r0;
+       bool            be;
+       bool            reset;
+};
+
 struct kvm_vcpu_arch {
        struct kvm_cpu_context ctxt;
 
@@ -297,6 +305,9 @@ struct kvm_vcpu_arch {
        /* Virtual SError ESR to restore when HCR_EL2.VSE is set */
        u64 vsesr_el2;
 
+       /* Additional reset state */
+       struct vcpu_reset_state reset_state;
+
        /* True when deferrable sysregs are loaded on the physical CPU,
         * see kvm_vcpu_load_sysregs and kvm_vcpu_put_sysregs. */
        bool sysregs_loaded_on_cpu;
index e1ec947..0c65685 100644 (file)
@@ -332,6 +332,17 @@ static inline void *phys_to_virt(phys_addr_t x)
 #define virt_addr_valid(kaddr)         \
        (_virt_addr_is_linear(kaddr) && _virt_addr_valid(kaddr))
 
+/*
+ * Given that the GIC architecture permits ITS implementations that can only be
+ * configured with a LPI table address once, GICv3 systems with many CPUs may
+ * end up reserving a lot of different regions after a kexec for their LPI
+ * tables (one per CPU), as we are forced to reuse the same memory after kexec
+ * (and thus reserve it persistently with EFI beforehand)
+ */
+#if defined(CONFIG_EFI) && defined(CONFIG_ARM_GIC_V3_ITS)
+# define INIT_MEMBLOCK_RESERVED_REGIONS        (INIT_MEMBLOCK_REGIONS + NR_CPUS + 1)
+#endif
+
 #include <asm-generic/memory_model.h>
 
 #endif
index 7689c7a..3e8063f 100644 (file)
@@ -16,6 +16,8 @@
 #ifndef __ASM_MMU_H
 #define __ASM_MMU_H
 
+#include <asm/cputype.h>
+
 #define MMCF_AARCH32   0x1     /* mm context flag for AArch32 executables */
 #define USER_ASID_BIT  48
 #define USER_ASID_FLAG (UL(1) << USER_ASID_BIT)
@@ -44,6 +46,48 @@ static inline bool arm64_kernel_unmapped_at_el0(void)
               cpus_have_const_cap(ARM64_UNMAP_KERNEL_AT_EL0);
 }
 
+static inline bool arm64_kernel_use_ng_mappings(void)
+{
+       bool tx1_bug;
+
+       /* What's a kpti? Use global mappings if we don't know. */
+       if (!IS_ENABLED(CONFIG_UNMAP_KERNEL_AT_EL0))
+               return false;
+
+       /*
+        * Note: this function is called before the CPU capabilities have
+        * been configured, so our early mappings will be global. If we
+        * later determine that kpti is required, then
+        * kpti_install_ng_mappings() will make them non-global.
+        */
+       if (arm64_kernel_unmapped_at_el0())
+               return true;
+
+       if (!IS_ENABLED(CONFIG_RANDOMIZE_BASE))
+               return false;
+
+       /*
+        * KASLR is enabled so we're going to be enabling kpti on non-broken
+        * CPUs regardless of their susceptibility to Meltdown. Rather
+        * than force everybody to go through the G -> nG dance later on,
+        * just put down non-global mappings from the beginning.
+        */
+       if (!IS_ENABLED(CONFIG_CAVIUM_ERRATUM_27456)) {
+               tx1_bug = false;
+#ifndef MODULE
+       } else if (!static_branch_likely(&arm64_const_caps_ready)) {
+               extern const struct midr_range cavium_erratum_27456_cpus[];
+
+               tx1_bug = is_midr_in_range_list(read_cpuid_id(),
+                                               cavium_erratum_27456_cpus);
+#endif
+       } else {
+               tx1_bug = __cpus_have_const_cap(ARM64_WORKAROUND_CAVIUM_27456);
+       }
+
+       return !tx1_bug && kaslr_offset() > 0;
+}
+
 typedef void (*bp_hardening_cb_t)(void);
 
 struct bp_hardening_data {
index 2ba6c6b..71abfc7 100644 (file)
@@ -36,4 +36,8 @@
 #include <arm_neon.h>
 #endif
 
+#ifdef CONFIG_CC_IS_CLANG
+#pragma clang diagnostic ignored "-Wincompatible-pointer-types"
+#endif
+
 #endif /* __ASM_NEON_INTRINSICS_H */
index 78b942c..986e41c 100644 (file)
@@ -37,8 +37,8 @@
 #define _PROT_DEFAULT          (PTE_TYPE_PAGE | PTE_AF | PTE_SHARED)
 #define _PROT_SECT_DEFAULT     (PMD_TYPE_SECT | PMD_SECT_AF | PMD_SECT_S)
 
-#define PTE_MAYBE_NG           (arm64_kernel_unmapped_at_el0() ? PTE_NG : 0)
-#define PMD_MAYBE_NG           (arm64_kernel_unmapped_at_el0() ? PMD_SECT_NG : 0)
+#define PTE_MAYBE_NG           (arm64_kernel_use_ng_mappings() ? PTE_NG : 0)
+#define PMD_MAYBE_NG           (arm64_kernel_use_ng_mappings() ? PMD_SECT_NG : 0)
 
 #define PROT_DEFAULT           (_PROT_DEFAULT | PTE_MAYBE_NG)
 #define PROT_SECT_DEFAULT      (_PROT_SECT_DEFAULT | PMD_MAYBE_NG)
index b3ef061..d88e56b 100644 (file)
@@ -1 +1,77 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+#ifndef _ASM_ARM64_XEN_PAGE_COHERENT_H
+#define _ASM_ARM64_XEN_PAGE_COHERENT_H
+
+#include <linux/dma-mapping.h>
+#include <asm/page.h>
 #include <xen/arm/page-coherent.h>
+
+static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
+               dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs)
+{
+       return dma_direct_alloc(hwdev, size, dma_handle, flags, attrs);
+}
+
+static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
+               void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs)
+{
+       dma_direct_free(hwdev, size, cpu_addr, dma_handle, attrs);
+}
+
+static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+
+       if (pfn_valid(pfn))
+               dma_direct_sync_single_for_cpu(hwdev, handle, size, dir);
+       else
+               __xen_dma_sync_single_for_cpu(hwdev, handle, size, dir);
+}
+
+static inline void xen_dma_sync_single_for_device(struct device *hwdev,
+               dma_addr_t handle, size_t size, enum dma_data_direction dir)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+       if (pfn_valid(pfn))
+               dma_direct_sync_single_for_device(hwdev, handle, size, dir);
+       else
+               __xen_dma_sync_single_for_device(hwdev, handle, size, dir);
+}
+
+static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
+            dma_addr_t dev_addr, unsigned long offset, size_t size,
+            enum dma_data_direction dir, unsigned long attrs)
+{
+       unsigned long page_pfn = page_to_xen_pfn(page);
+       unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
+       unsigned long compound_pages =
+               (1<<compound_order(page)) * XEN_PFN_PER_PAGE;
+       bool local = (page_pfn <= dev_pfn) &&
+               (dev_pfn - page_pfn < compound_pages);
+
+       if (local)
+               dma_direct_map_page(hwdev, page, offset, size, dir, attrs);
+       else
+               __xen_dma_map_page(hwdev, page, dev_addr, offset, size, dir, attrs);
+}
+
+static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
+               size_t size, enum dma_data_direction dir, unsigned long attrs)
+{
+       unsigned long pfn = PFN_DOWN(handle);
+       /*
+        * Dom0 is mapped 1:1, while the Linux page can be spanned accross
+        * multiple Xen page, it's not possible to have a mix of local and
+        * foreign Xen page. Dom0 is mapped 1:1, so calling pfn_valid on a
+        * foreign mfn will always return false. If the page is local we can
+        * safely call the native dma_ops function, otherwise we call the xen
+        * specific function.
+        */
+       if (pfn_valid(pfn))
+               dma_direct_unmap_page(hwdev, handle, size, dir, attrs);
+       else
+               __xen_dma_unmap_page(hwdev, handle, size, dir, attrs);
+}
+
+#endif /* _ASM_ARM64_XEN_PAGE_COHERENT_H */
index 09ac548..9950bb0 100644 (file)
@@ -553,7 +553,7 @@ static const struct midr_range arm64_repeat_tlbi_cpus[] = {
 #endif
 
 #ifdef CONFIG_CAVIUM_ERRATUM_27456
-static const struct midr_range cavium_erratum_27456_cpus[] = {
+const struct midr_range cavium_erratum_27456_cpus[] = {
        /* Cavium ThunderX, T88 pass 1.x - 2.1 */
        MIDR_RANGE(MIDR_THUNDERX, 0, 0, 1, 1),
        /* Cavium ThunderX, T81 pass 1.0 */
index 4f27239..f6d84e2 100644 (file)
@@ -983,7 +983,7 @@ static bool unmap_kernel_at_el0(const struct arm64_cpu_capabilities *entry,
 
        /* Useful for KASLR robustness */
        if (IS_ENABLED(CONFIG_RANDOMIZE_BASE))
-               return true;
+               return kaslr_offset() > 0;
 
        /* Don't force KPTI for CPUs that are not vulnerable */
        if (is_midr_in_range_list(read_cpuid_id(), kpti_safe_list))
@@ -1003,7 +1003,12 @@ kpti_install_ng_mappings(const struct arm64_cpu_capabilities *__unused)
        static bool kpti_applied = false;
        int cpu = smp_processor_id();
 
-       if (kpti_applied)
+       /*
+        * We don't need to rewrite the page-tables if either we've done
+        * it already or we have KASLR enabled and therefore have not
+        * created any global mappings at all.
+        */
+       if (kpti_applied || kaslr_offset() > 0)
                return;
 
        remap_fn = (void *)__pa_symbol(idmap_kpti_install_ng_mappings);
index c721367..eecf792 100644 (file)
@@ -475,6 +475,7 @@ ENDPROC(__primary_switched)
 
 ENTRY(kimage_vaddr)
        .quad           _text - TEXT_OFFSET
+EXPORT_SYMBOL(kimage_vaddr)
 
 /*
  * If we're fortunate enough to boot at EL2, ensure that the world is
@@ -538,8 +539,7 @@ set_hcr:
        /* GICv3 system register access */
        mrs     x0, id_aa64pfr0_el1
        ubfx    x0, x0, #24, #4
-       cmp     x0, #1
-       b.ne    3f
+       cbz     x0, 3f
 
        mrs_s   x0, SYS_ICC_SRE_EL2
        orr     x0, x0, #ICC_SRE_EL2_SRE        // Set ICC_SRE_EL2.SRE==1
index 29cdc99..9859e11 100644 (file)
@@ -299,8 +299,10 @@ int swsusp_arch_suspend(void)
                dcache_clean_range(__idmap_text_start, __idmap_text_end);
 
                /* Clean kvm setup code to PoC? */
-               if (el2_reset_needed())
+               if (el2_reset_needed()) {
                        dcache_clean_range(__hyp_idmap_text_start, __hyp_idmap_text_end);
+                       dcache_clean_range(__hyp_text_start, __hyp_text_end);
+               }
 
                /* make the crash dump kernel image protected again */
                crash_post_resume();
index e1261fb..17f325b 100644 (file)
@@ -28,6 +28,8 @@
 #include <asm/virt.h>
 
        .text
+       .pushsection    .hyp.text, "ax"
+
        .align 11
 
 ENTRY(__hyp_stub_vectors)
index f0e6ab8..b09b6f7 100644 (file)
@@ -14,6 +14,7 @@
 #include <linux/sched.h>
 #include <linux/types.h>
 
+#include <asm/cacheflush.h>
 #include <asm/fixmap.h>
 #include <asm/kernel-pgtable.h>
 #include <asm/memory.h>
@@ -43,7 +44,7 @@ static __init u64 get_kaslr_seed(void *fdt)
        return ret;
 }
 
-static __init const u8 *get_cmdline(void *fdt)
+static __init const u8 *kaslr_get_cmdline(void *fdt)
 {
        static __initconst const u8 default_cmdline[] = CONFIG_CMDLINE;
 
@@ -87,6 +88,7 @@ u64 __init kaslr_early_init(u64 dt_phys)
         * we end up running with module randomization disabled.
         */
        module_alloc_base = (u64)_etext - MODULES_VSIZE;
+       __flush_dcache_area(&module_alloc_base, sizeof(module_alloc_base));
 
        /*
         * Try to map the FDT early. If this fails, we simply bail,
@@ -109,7 +111,7 @@ u64 __init kaslr_early_init(u64 dt_phys)
         * Check if 'nokaslr' appears on the command line, and
         * return 0 if that is the case.
         */
-       cmdline = get_cmdline(fdt);
+       cmdline = kaslr_get_cmdline(fdt);
        str = strstr(cmdline, "nokaslr");
        if (str == cmdline || (str > cmdline && *(str - 1) == ' '))
                return 0;
@@ -169,5 +171,8 @@ u64 __init kaslr_early_init(u64 dt_phys)
        module_alloc_base += (module_range * (seed & ((1 << 21) - 1))) >> 21;
        module_alloc_base &= PAGE_MASK;
 
+       __flush_dcache_area(&module_alloc_base, sizeof(module_alloc_base));
+       __flush_dcache_area(&memstart_offset_seed, sizeof(memstart_offset_seed));
+
        return offset;
 }
index 10e3386..5887133 100644 (file)
@@ -87,7 +87,9 @@ static int setup_dtb(struct kimage *image,
 
        /* add kaslr-seed */
        ret = fdt_delprop(dtb, off, FDT_PROP_KASLR_SEED);
-       if (ret && (ret != -FDT_ERR_NOTFOUND))
+       if  (ret == -FDT_ERR_NOTFOUND)
+               ret = 0;
+       else if (ret)
                goto out;
 
        if (rng_is_initialized()) {
@@ -118,10 +120,12 @@ static int create_dtb(struct kimage *image,
 {
        void *buf;
        size_t buf_size;
+       size_t cmdline_len;
        int ret;
 
+       cmdline_len = cmdline ? strlen(cmdline) : 0;
        buf_size = fdt_totalsize(initial_boot_params)
-                       + strlen(cmdline) + DTB_EXTRA_SPACE;
+                       + cmdline_len + DTB_EXTRA_SPACE;
 
        for (;;) {
                buf = vmalloc(buf_size);
index 2a5b338..f17afb9 100644 (file)
@@ -478,13 +478,13 @@ bool arch_within_kprobe_blacklist(unsigned long addr)
            addr < (unsigned long)__entry_text_end) ||
            (addr >= (unsigned long)__idmap_text_start &&
            addr < (unsigned long)__idmap_text_end) ||
+           (addr >= (unsigned long)__hyp_text_start &&
+           addr < (unsigned long)__hyp_text_end) ||
            !!search_exception_tables(addr))
                return true;
 
        if (!is_kernel_in_hyp_mode()) {
-               if ((addr >= (unsigned long)__hyp_text_start &&
-                   addr < (unsigned long)__hyp_text_end) ||
-                   (addr >= (unsigned long)__hyp_idmap_text_start &&
+               if ((addr >= (unsigned long)__hyp_idmap_text_start &&
                    addr < (unsigned long)__hyp_idmap_text_end))
                        return true;
        }
index 9dce33b..ddaea0f 100644 (file)
@@ -1702,19 +1702,20 @@ void syscall_trace_exit(struct pt_regs *regs)
 }
 
 /*
- * SPSR_ELx bits which are always architecturally RES0 per ARM DDI 0487C.a
- * We also take into account DIT (bit 24), which is not yet documented, and
- * treat PAN and UAO as RES0 bits, as they are meaningless at EL0, and may be
- * allocated an EL0 meaning in future.
+ * SPSR_ELx bits which are always architecturally RES0 per ARM DDI 0487D.a.
+ * We permit userspace to set SSBS (AArch64 bit 12, AArch32 bit 23) which is
+ * not described in ARM DDI 0487D.a.
+ * We treat PAN and UAO as RES0 bits, as they are meaningless at EL0, and may
+ * be allocated an EL0 meaning in future.
  * Userspace cannot use these until they have an architectural meaning.
  * Note that this follows the SPSR_ELx format, not the AArch32 PSR format.
  * We also reserve IL for the kernel; SS is handled dynamically.
  */
 #define SPSR_EL1_AARCH64_RES0_BITS \
-       (GENMASK_ULL(63,32) | GENMASK_ULL(27, 25) | GENMASK_ULL(23, 22) | \
-        GENMASK_ULL(20, 10) | GENMASK_ULL(5, 5))
+       (GENMASK_ULL(63, 32) | GENMASK_ULL(27, 25) | GENMASK_ULL(23, 22) | \
+        GENMASK_ULL(20, 13) | GENMASK_ULL(11, 10) | GENMASK_ULL(5, 5))
 #define SPSR_EL1_AARCH32_RES0_BITS \
-       (GENMASK_ULL(63,32) | GENMASK_ULL(23, 22) | GENMASK_ULL(20,20))
+       (GENMASK_ULL(63, 32) | GENMASK_ULL(22, 22) | GENMASK_ULL(20, 20))
 
 static int valid_compat_regs(struct user_pt_regs *regs)
 {
index 4b0e123..0098493 100644 (file)
@@ -313,7 +313,6 @@ void __init setup_arch(char **cmdline_p)
        arm64_memblock_init();
 
        paging_init();
-       efi_apply_persistent_mem_reservations();
 
        acpi_table_upgrade();
 
@@ -340,6 +339,9 @@ void __init setup_arch(char **cmdline_p)
        smp_init_cpus();
        smp_build_mpidr_hash();
 
+       /* Init percpu seeds for random tags after cpus are set up. */
+       kasan_init_tags();
+
 #ifdef CONFIG_ARM64_SW_TTBR0_PAN
        /*
         * Make sure init_thread_info.ttbr0 always generates translation
index b0b1478..421ebf6 100644 (file)
@@ -23,6 +23,7 @@
 #include <kvm/arm_psci.h>
 
 #include <asm/cpufeature.h>
+#include <asm/kprobes.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_host.h>
@@ -107,6 +108,7 @@ static void activate_traps_vhe(struct kvm_vcpu *vcpu)
 
        write_sysreg(kvm_get_hyp_vector(), vbar_el1);
 }
+NOKPROBE_SYMBOL(activate_traps_vhe);
 
 static void __hyp_text __activate_traps_nvhe(struct kvm_vcpu *vcpu)
 {
@@ -154,6 +156,7 @@ static void deactivate_traps_vhe(void)
        write_sysreg(CPACR_EL1_DEFAULT, cpacr_el1);
        write_sysreg(vectors, vbar_el1);
 }
+NOKPROBE_SYMBOL(deactivate_traps_vhe);
 
 static void __hyp_text __deactivate_traps_nvhe(void)
 {
@@ -513,6 +516,7 @@ int kvm_vcpu_run_vhe(struct kvm_vcpu *vcpu)
 
        return exit_code;
 }
+NOKPROBE_SYMBOL(kvm_vcpu_run_vhe);
 
 /* Switch to the guest for legacy non-VHE systems */
 int __hyp_text __kvm_vcpu_run_nvhe(struct kvm_vcpu *vcpu)
@@ -620,6 +624,7 @@ static void __hyp_call_panic_vhe(u64 spsr, u64 elr, u64 par,
              read_sysreg_el2(esr),   read_sysreg_el2(far),
              read_sysreg(hpfar_el2), par, vcpu);
 }
+NOKPROBE_SYMBOL(__hyp_call_panic_vhe);
 
 void __hyp_text __noreturn hyp_panic(struct kvm_cpu_context *host_ctxt)
 {
index 68d6f7c..b426e2c 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/compiler.h>
 #include <linux/kvm_host.h>
 
+#include <asm/kprobes.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_emulate.h>
 #include <asm/kvm_hyp.h>
@@ -98,12 +99,14 @@ void sysreg_save_host_state_vhe(struct kvm_cpu_context *ctxt)
 {
        __sysreg_save_common_state(ctxt);
 }
+NOKPROBE_SYMBOL(sysreg_save_host_state_vhe);
 
 void sysreg_save_guest_state_vhe(struct kvm_cpu_context *ctxt)
 {
        __sysreg_save_common_state(ctxt);
        __sysreg_save_el2_return_state(ctxt);
 }
+NOKPROBE_SYMBOL(sysreg_save_guest_state_vhe);
 
 static void __hyp_text __sysreg_restore_common_state(struct kvm_cpu_context *ctxt)
 {
@@ -188,12 +191,14 @@ void sysreg_restore_host_state_vhe(struct kvm_cpu_context *ctxt)
 {
        __sysreg_restore_common_state(ctxt);
 }
+NOKPROBE_SYMBOL(sysreg_restore_host_state_vhe);
 
 void sysreg_restore_guest_state_vhe(struct kvm_cpu_context *ctxt)
 {
        __sysreg_restore_common_state(ctxt);
        __sysreg_restore_el2_return_state(ctxt);
 }
+NOKPROBE_SYMBOL(sysreg_restore_guest_state_vhe);
 
 void __hyp_text __sysreg32_save_state(struct kvm_vcpu *vcpu)
 {
index b72a3dd..f16a5f8 100644 (file)
@@ -32,6 +32,7 @@
 #include <asm/kvm_arm.h>
 #include <asm/kvm_asm.h>
 #include <asm/kvm_coproc.h>
+#include <asm/kvm_emulate.h>
 #include <asm/kvm_mmu.h>
 
 /* Maximum phys_shift supported for any VM on this host */
@@ -105,16 +106,33 @@ int kvm_arch_vm_ioctl_check_extension(struct kvm *kvm, long ext)
  * This function finds the right table above and sets the registers on
  * the virtual CPU struct to their architecturally defined reset
  * values.
+ *
+ * Note: This function can be called from two paths: The KVM_ARM_VCPU_INIT
+ * ioctl or as part of handling a request issued by another VCPU in the PSCI
+ * handling code.  In the first case, the VCPU will not be loaded, and in the
+ * second case the VCPU will be loaded.  Because this function operates purely
+ * on the memory-backed valus of system registers, we want to do a full put if
+ * we were loaded (handling a request) and load the values back at the end of
+ * the function.  Otherwise we leave the state alone.  In both cases, we
+ * disable preemption around the vcpu reset as we would otherwise race with
+ * preempt notifiers which also call put/load.
  */
 int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
 {
        const struct kvm_regs *cpu_reset;
+       int ret = -EINVAL;
+       bool loaded;
+
+       preempt_disable();
+       loaded = (vcpu->cpu != -1);
+       if (loaded)
+               kvm_arch_vcpu_put(vcpu);
 
        switch (vcpu->arch.target) {
        default:
                if (test_bit(KVM_ARM_VCPU_EL1_32BIT, vcpu->arch.features)) {
                        if (!cpu_has_32bit_el1())
-                               return -EINVAL;
+                               goto out;
                        cpu_reset = &default_regs_reset32;
                } else {
                        cpu_reset = &default_regs_reset;
@@ -129,6 +147,29 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
        /* Reset system registers */
        kvm_reset_sys_regs(vcpu);
 
+       /*
+        * Additional reset state handling that PSCI may have imposed on us.
+        * Must be done after all the sys_reg reset.
+        */
+       if (vcpu->arch.reset_state.reset) {
+               unsigned long target_pc = vcpu->arch.reset_state.pc;
+
+               /* Gracefully handle Thumb2 entry point */
+               if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) {
+                       target_pc &= ~1UL;
+                       vcpu_set_thumb(vcpu);
+               }
+
+               /* Propagate caller endianness */
+               if (vcpu->arch.reset_state.be)
+                       kvm_vcpu_set_be(vcpu);
+
+               *vcpu_pc(vcpu) = target_pc;
+               vcpu_set_reg(vcpu, 0, vcpu->arch.reset_state.r0);
+
+               vcpu->arch.reset_state.reset = false;
+       }
+
        /* Reset PMU */
        kvm_pmu_vcpu_reset(vcpu);
 
@@ -137,7 +178,12 @@ int kvm_reset_vcpu(struct kvm_vcpu *vcpu)
                vcpu->arch.workaround_flags |= VCPU_WORKAROUND_2_FLAG;
 
        /* Reset timer */
-       return kvm_timer_vcpu_reset(vcpu);
+       ret = kvm_timer_vcpu_reset(vcpu);
+out:
+       if (loaded)
+               kvm_arch_vcpu_load(vcpu, smp_processor_id());
+       preempt_enable();
+       return ret;
 }
 
 void kvm_set_ipa_limit(void)
index e3e3722..c936aa4 100644 (file)
@@ -314,12 +314,29 @@ static bool trap_raz_wi(struct kvm_vcpu *vcpu,
                return read_zero(vcpu, p);
 }
 
-static bool trap_undef(struct kvm_vcpu *vcpu,
-                      struct sys_reg_params *p,
-                      const struct sys_reg_desc *r)
+/*
+ * ARMv8.1 mandates at least a trivial LORegion implementation, where all the
+ * RW registers are RES0 (which we can implement as RAZ/WI). On an ARMv8.0
+ * system, these registers should UNDEF. LORID_EL1 being a RO register, we
+ * treat it separately.
+ */
+static bool trap_loregion(struct kvm_vcpu *vcpu,
+                         struct sys_reg_params *p,
+                         const struct sys_reg_desc *r)
 {
-       kvm_inject_undefined(vcpu);
-       return false;
+       u64 val = read_sanitised_ftr_reg(SYS_ID_AA64MMFR1_EL1);
+       u32 sr = sys_reg((u32)r->Op0, (u32)r->Op1,
+                        (u32)r->CRn, (u32)r->CRm, (u32)r->Op2);
+
+       if (!(val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))) {
+               kvm_inject_undefined(vcpu);
+               return false;
+       }
+
+       if (p->is_write && sr == SYS_LORID_EL1)
+               return write_to_read_only(vcpu, p, r);
+
+       return trap_raz_wi(vcpu, p, r);
 }
 
 static bool trap_oslsr_el1(struct kvm_vcpu *vcpu,
@@ -1048,11 +1065,6 @@ static u64 read_id_reg(struct sys_reg_desc const *r, bool raz)
                if (val & ptrauth_mask)
                        kvm_debug("ptrauth unsupported for guests, suppressing\n");
                val &= ~ptrauth_mask;
-       } else if (id == SYS_ID_AA64MMFR1_EL1) {
-               if (val & (0xfUL << ID_AA64MMFR1_LOR_SHIFT))
-                       kvm_debug("LORegions unsupported for guests, suppressing\n");
-
-               val &= ~(0xfUL << ID_AA64MMFR1_LOR_SHIFT);
        }
 
        return val;
@@ -1338,11 +1350,11 @@ static const struct sys_reg_desc sys_reg_descs[] = {
        { SYS_DESC(SYS_MAIR_EL1), access_vm_reg, reset_unknown, MAIR_EL1 },
        { SYS_DESC(SYS_AMAIR_EL1), access_vm_reg, reset_amair_el1, AMAIR_EL1 },
 
-       { SYS_DESC(SYS_LORSA_EL1), trap_undef },
-       { SYS_DESC(SYS_LOREA_EL1), trap_undef },
-       { SYS_DESC(SYS_LORN_EL1), trap_undef },
-       { SYS_DESC(SYS_LORC_EL1), trap_undef },
-       { SYS_DESC(SYS_LORID_EL1), trap_undef },
+       { SYS_DESC(SYS_LORSA_EL1), trap_loregion },
+       { SYS_DESC(SYS_LOREA_EL1), trap_loregion },
+       { SYS_DESC(SYS_LORN_EL1), trap_loregion },
+       { SYS_DESC(SYS_LORC_EL1), trap_loregion },
+       { SYS_DESC(SYS_LORID_EL1), trap_loregion },
 
        { SYS_DESC(SYS_VBAR_EL1), NULL, reset_val, VBAR_EL1, 0 },
        { SYS_DESC(SYS_DISR_EL1), NULL, reset_val, DISR_EL1, 0 },
@@ -2596,7 +2608,9 @@ void kvm_reset_sys_regs(struct kvm_vcpu *vcpu)
        table = get_target_table(vcpu->arch.target, true, &num);
        reset_sys_reg_descs(vcpu, table, num);
 
-       for (num = 1; num < NR_SYS_REGS; num++)
-               if (__vcpu_sys_reg(vcpu, num) == 0x4242424242424242)
-                       panic("Didn't reset __vcpu_sys_reg(%zi)", num);
+       for (num = 1; num < NR_SYS_REGS; num++) {
+               if (WARN(__vcpu_sys_reg(vcpu, num) == 0x4242424242424242,
+                        "Didn't reset __vcpu_sys_reg(%zi)\n", num))
+                       break;
+       }
 }
index fb09084..78c0a72 100644 (file)
@@ -466,9 +466,7 @@ void arch_setup_dma_ops(struct device *dev, u64 dma_base, u64 size,
        __iommu_setup_dma_ops(dev, dma_base, size, iommu);
 
 #ifdef CONFIG_XEN
-       if (xen_initial_domain()) {
-               dev->archdata.dev_dma_ops = dev->dma_ops;
+       if (xen_initial_domain())
                dev->dma_ops = xen_dma_ops;
-       }
 #endif
 }
index fcb1f2a..99bb8fa 100644 (file)
@@ -286,74 +286,73 @@ static void note_page(struct pg_state *st, unsigned long addr, unsigned level,
 
 }
 
-static void walk_pte(struct pg_state *st, pmd_t *pmdp, unsigned long start)
+static void walk_pte(struct pg_state *st, pmd_t *pmdp, unsigned long start,
+                    unsigned long end)
 {
-       pte_t *ptep = pte_offset_kernel(pmdp, 0UL);
-       unsigned long addr;
-       unsigned i;
+       unsigned long addr = start;
+       pte_t *ptep = pte_offset_kernel(pmdp, start);
 
-       for (i = 0; i < PTRS_PER_PTE; i++, ptep++) {
-               addr = start + i * PAGE_SIZE;
+       do {
                note_page(st, addr, 4, READ_ONCE(pte_val(*ptep)));
-       }
+       } while (ptep++, addr += PAGE_SIZE, addr != end);
 }
 
-static void walk_pmd(struct pg_state *st, pud_t *pudp, unsigned long start)
+static void walk_pmd(struct pg_state *st, pud_t *pudp, unsigned long start,
+                    unsigned long end)
 {
-       pmd_t *pmdp = pmd_offset(pudp, 0UL);
-       unsigned long addr;
-       unsigned i;
+       unsigned long next, addr = start;
+       pmd_t *pmdp = pmd_offset(pudp, start);
 
-       for (i = 0; i < PTRS_PER_PMD; i++, pmdp++) {
+       do {
                pmd_t pmd = READ_ONCE(*pmdp);
+               next = pmd_addr_end(addr, end);
 
-               addr = start + i * PMD_SIZE;
                if (pmd_none(pmd) || pmd_sect(pmd)) {
                        note_page(st, addr, 3, pmd_val(pmd));
                } else {
                        BUG_ON(pmd_bad(pmd));
-                       walk_pte(st, pmdp, addr);
+                       walk_pte(st, pmdp, addr, next);
                }
-       }
+       } while (pmdp++, addr = next, addr != end);
 }
 
-static void walk_pud(struct pg_state *st, pgd_t *pgdp, unsigned long start)
+static void walk_pud(struct pg_state *st, pgd_t *pgdp, unsigned long start,
+                    unsigned long end)
 {
-       pud_t *pudp = pud_offset(pgdp, 0UL);
-       unsigned long addr;
-       unsigned i;
+       unsigned long next, addr = start;
+       pud_t *pudp = pud_offset(pgdp, start);
 
-       for (i = 0; i < PTRS_PER_PUD; i++, pudp++) {
+       do {
                pud_t pud = READ_ONCE(*pudp);
+               next = pud_addr_end(addr, end);
 
-               addr = start + i * PUD_SIZE;
                if (pud_none(pud) || pud_sect(pud)) {
                        note_page(st, addr, 2, pud_val(pud));
                } else {
                        BUG_ON(pud_bad(pud));
-                       walk_pmd(st, pudp, addr);
+                       walk_pmd(st, pudp, addr, next);
                }
-       }
+       } while (pudp++, addr = next, addr != end);
 }
 
 static void walk_pgd(struct pg_state *st, struct mm_struct *mm,
                     unsigned long start)
 {
-       pgd_t *pgdp = pgd_offset(mm, 0UL);
-       unsigned i;
-       unsigned long addr;
+       unsigned long end = (start < TASK_SIZE_64) ? TASK_SIZE_64 : 0;
+       unsigned long next, addr = start;
+       pgd_t *pgdp = pgd_offset(mm, start);
 
-       for (i = 0; i < PTRS_PER_PGD; i++, pgdp++) {
+       do {
                pgd_t pgd = READ_ONCE(*pgdp);
+               next = pgd_addr_end(addr, end);
 
-               addr = start + i * PGDIR_SIZE;
                if (pgd_none(pgd)) {
                        note_page(st, addr, 1, pgd_val(pgd));
                } else {
                        BUG_ON(pgd_bad(pgd));
-                       walk_pud(st, pgdp, addr);
+                       walk_pud(st, pgdp, addr, next);
                }
-       }
+       } while (pgdp++, addr = next, addr != end);
 }
 
 void ptdump_walk_pgd(struct seq_file *m, struct ptdump_info *info)
index 30695a8..5c9073b 100644 (file)
@@ -33,7 +33,11 @@ void sync_icache_aliases(void *kaddr, unsigned long len)
                __clean_dcache_area_pou(kaddr, len);
                __flush_icache_all();
        } else {
-               flush_icache_range(addr, addr + len);
+               /*
+                * Don't issue kick_all_cpus_sync() after I-cache invalidation
+                * for user mappings.
+                */
+               __flush_icache_range(addr, addr + len);
        }
 }
 
index 4b55b15..f37a86d 100644 (file)
@@ -252,8 +252,6 @@ void __init kasan_init(void)
        memset(kasan_early_shadow_page, KASAN_SHADOW_INIT, PAGE_SIZE);
        cpu_replace_ttbr1(lm_alias(swapper_pg_dir));
 
-       kasan_init_tags();
-
        /* At this point kasan is fully initialized. Enable error messages */
        init_task.kasan_depth = 0;
        pr_info("KernelAddressSanitizer initialized\n");
index 33a2c94..63b4a17 100644 (file)
@@ -30,6 +30,7 @@ generic-y += pgalloc.h
 generic-y += preempt.h
 generic-y += segment.h
 generic-y += serial.h
+generic-y += shmparam.h
 generic-y += tlbflush.h
 generic-y += topology.h
 generic-y += trace_clock.h
index ecae6b3..c1dfa9c 100644 (file)
@@ -15,6 +15,31 @@ extern void iounmap(void *addr);
 extern int remap_area_pages(unsigned long address, phys_addr_t phys_addr,
                size_t size, unsigned long flags);
 
+/*
+ * I/O memory access primitives. Reads are ordered relative to any
+ * following Normal memory access. Writes are ordered relative to any prior
+ * Normal memory access.
+ *
+ * For CACHEV1 (807, 810), store instruction could fast retire, so we need
+ * another mb() to prevent st fast retire.
+ *
+ * For CACHEV2 (860), store instruction with PAGE_ATTR_NO_BUFFERABLE won't
+ * fast retire.
+ */
+#define readb(c)               ({ u8  __v = readb_relaxed(c); rmb(); __v; })
+#define readw(c)               ({ u16 __v = readw_relaxed(c); rmb(); __v; })
+#define readl(c)               ({ u32 __v = readl_relaxed(c); rmb(); __v; })
+
+#ifdef CONFIG_CPU_HAS_CACHEV2
+#define writeb(v,c)            ({ wmb(); writeb_relaxed((v),(c)); })
+#define writew(v,c)            ({ wmb(); writew_relaxed((v),(c)); })
+#define writel(v,c)            ({ wmb(); writel_relaxed((v),(c)); })
+#else
+#define writeb(v,c)            ({ wmb(); writeb_relaxed((v),(c)); mb(); })
+#define writew(v,c)            ({ wmb(); writew_relaxed((v),(c)); mb(); })
+#define writel(v,c)            ({ wmb(); writel_relaxed((v),(c)); mb(); })
+#endif
+
 #define ioremap_nocache(phy, sz)       ioremap(phy, sz)
 #define ioremap_wc ioremap_nocache
 #define ioremap_wt ioremap_nocache
index bf4f4a0..d213bb4 100644 (file)
@@ -24,41 +24,34 @@ static inline void pmd_populate(struct mm_struct *mm, pmd_t *pmd,
 
 extern void pgd_init(unsigned long *p);
 
-static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm,
-                                       unsigned long address)
+static inline pte_t *pte_alloc_one_kernel(struct mm_struct *mm)
 {
        pte_t *pte;
-       unsigned long *kaddr, i;
+       unsigned long i;
 
-       pte = (pte_t *) __get_free_pages(GFP_KERNEL | __GFP_RETRY_MAYFAIL,
-                                        PTE_ORDER);
-       kaddr = (unsigned long *)pte;
-       if (address & 0x80000000)
-               for (i = 0; i < (PAGE_SIZE/4); i++)
-                       *(kaddr + i) = 0x1;
-       else
-               clear_page(kaddr);
+       pte = (pte_t *) __get_free_page(GFP_KERNEL);
+       if (!pte)
+               return NULL;
+
+       for (i = 0; i < PAGE_SIZE/sizeof(pte_t); i++)
+               (pte + i)->pte_low = _PAGE_GLOBAL;
 
        return pte;
 }
 
-static inline struct page *pte_alloc_one(struct mm_struct *mm,
-                                               unsigned long address)
+static inline struct page *pte_alloc_one(struct mm_struct *mm)
 {
        struct page *pte;
-       unsigned long *kaddr, i;
-
-       pte = alloc_pages(GFP_KERNEL | __GFP_RETRY_MAYFAIL, PTE_ORDER);
-       if (pte) {
-               kaddr = kmap_atomic(pte);
-               if (address & 0x80000000) {
-                       for (i = 0; i < (PAGE_SIZE/4); i++)
-                               *(kaddr + i) = 0x1;
-               } else
-                       clear_page(kaddr);
-               kunmap_atomic(kaddr);
-               pgtable_page_ctor(pte);
+
+       pte = alloc_pages(GFP_KERNEL | __GFP_ZERO, 0);
+       if (!pte)
+               return NULL;
+
+       if (!pgtable_page_ctor(pte)) {
+               __free_page(pte);
+               return NULL;
        }
+
        return pte;
 }
 
index edfcbb2..dcea277 100644 (file)
@@ -45,8 +45,8 @@
        ((pte_t *)page_address(pmd_page(*(dir))) + __pte_offset_t(address))
 #define pmd_page(pmd)  (pfn_to_page(pmd_phys(pmd) >> PAGE_SHIFT))
 #define pte_clear(mm, addr, ptep)      set_pte((ptep), \
-                       (((unsigned int)addr&0x80000000)?__pte(1):__pte(0)))
-#define pte_none(pte)  (!(pte_val(pte)&0xfffffffe))
+       (((unsigned int) addr & PAGE_OFFSET) ? __pte(_PAGE_GLOBAL) : __pte(0)))
+#define pte_none(pte)          (!(pte_val(pte) & ~_PAGE_GLOBAL))
 #define pte_present(pte)       (pte_val(pte) & _PAGE_PRESENT)
 #define pte_pfn(x)     ((unsigned long)((x).pte_low >> PAGE_SHIFT))
 #define pfn_pte(pfn, prot) __pte(((unsigned long long)(pfn) << PAGE_SHIFT) \
@@ -241,6 +241,11 @@ static inline pte_t pte_mkyoung(pte_t pte)
 
 #define pgd_index(address)     ((address) >> PGDIR_SHIFT)
 
+#define __HAVE_PHYS_MEM_ACCESS_PROT
+struct file;
+extern pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                                    unsigned long size, pgprot_t vma_prot);
+
 /*
  * Macro to make mark a page protection value as "uncacheable".  Note
  * that "protection" is really a misnomer here as the protection value
index 8f45481..21e0bd5 100644 (file)
@@ -49,7 +49,7 @@ struct thread_struct {
 };
 
 #define INIT_THREAD  { \
-       .ksp = (unsigned long) init_thread_union.stack + THREAD_SIZE, \
+       .ksp = sizeof(init_stack) + (unsigned long) &init_stack, \
        .sr = DEFAULT_PSR_VALUE, \
 }
 
@@ -95,7 +95,7 @@ unsigned long get_wchan(struct task_struct *p);
 #define KSTK_ESP(tsk)          (task_pt_regs(tsk)->usp)
 
 #define task_pt_regs(p) \
-       ((struct pt_regs *)(THREAD_SIZE + p->stack) - 1)
+       ((struct pt_regs *)(THREAD_SIZE + task_stack_page(p)) - 1)
 
 #define cpu_relax() barrier()
 
index 659253e..d67f977 100644 (file)
@@ -38,7 +38,11 @@ void show_stack(struct task_struct *task, unsigned long *stack)
                if (task)
                        stack = (unsigned long *)thread_saved_fp(task);
                else
+#ifdef CONFIG_STACKTRACE
+                       asm volatile("mov %0, r8\n":"=r"(stack)::"memory");
+#else
                        stack = (unsigned long *)&stack;
+#endif
        }
 
        show_trace(stack);
index 65abab0..b5ad7d9 100644 (file)
@@ -12,7 +12,7 @@
 #include <linux/spinlock.h>
 #include <asm/pgtable.h>
 
-#if defined(__CSKYABIV2__)
+#ifdef CONFIG_CPU_CK810
 #define IS_BSR32(hi16, lo16)           (((hi16) & 0xFC00) == 0xE000)
 #define IS_JSRI32(hi16, lo16)          ((hi16) == 0xEAE0)
 
        *(uint16_t *)(addr) = 0xE8Fa;           \
        *((uint16_t *)(addr) + 1) = 0x0000;     \
 } while (0)
+
+static void jsri_2_lrw_jsr(uint32_t *location)
+{
+       uint16_t *location_tmp = (uint16_t *)location;
+
+       if (IS_BSR32(*location_tmp, *(location_tmp + 1)))
+               return;
+
+       if (IS_JSRI32(*location_tmp, *(location_tmp + 1))) {
+               /* jsri 0x...  --> lrw r26, 0x... */
+               CHANGE_JSRI_TO_LRW(location);
+               /* lsli r0, r0 --> jsr r26 */
+               SET_JSR32_R26(location + 1);
+       }
+}
+#else
+static void inline jsri_2_lrw_jsr(uint32_t *location)
+{
+       return;
+}
 #endif
 
 int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
@@ -35,9 +55,6 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
        Elf32_Sym       *sym;
        uint32_t        *location;
        short           *temp;
-#if defined(__CSKYABIV2__)
-       uint16_t        *location_tmp;
-#endif
 
        for (i = 0; i < sechdrs[relsec].sh_size / sizeof(*rel); i++) {
                /* This is where to make the change */
@@ -59,18 +76,7 @@ int apply_relocate_add(Elf32_Shdr *sechdrs, const char *strtab,
                case R_CSKY_PCRELJSR_IMM11BY2:
                        break;
                case R_CSKY_PCRELJSR_IMM26BY2:
-#if defined(__CSKYABIV2__)
-                       location_tmp = (uint16_t *)location;
-                       if (IS_BSR32(*location_tmp, *(location_tmp + 1)))
-                               break;
-
-                       if (IS_JSRI32(*location_tmp, *(location_tmp + 1))) {
-                               /* jsri 0x...  --> lrw r26, 0x... */
-                               CHANGE_JSRI_TO_LRW(location);
-                               /* lsli r0, r0 --> jsr r26 */
-                               SET_JSR32_R26(location + 1);
-                       }
-#endif
+                       jsri_2_lrw_jsr(location);
                        break;
                case R_CSKY_ADDR_HI16:
                        temp = ((short  *)location) + 1;
index 57f1afe..f2f12ff 100644 (file)
@@ -8,6 +8,7 @@
 #include <linux/ptrace.h>
 #include <linux/regset.h>
 #include <linux/sched.h>
+#include <linux/sched/task_stack.h>
 #include <linux/signal.h>
 #include <linux/smp.h>
 #include <linux/uaccess.h>
@@ -159,7 +160,7 @@ static int fpr_set(struct task_struct *target,
 static const struct user_regset csky_regsets[] = {
        [REGSET_GPR] = {
                .core_note_type = NT_PRSTATUS,
-               .n = ELF_NGREG,
+               .n = sizeof(struct pt_regs) / sizeof(u32),
                .size = sizeof(u32),
                .align = sizeof(u32),
                .get = &gpr_get,
index ddc4dd7..b07a534 100644 (file)
@@ -160,7 +160,8 @@ int __cpu_up(unsigned int cpu, struct task_struct *tidle)
 {
        unsigned long mask = 1 << cpu;
 
-       secondary_stack = (unsigned int)tidle->stack + THREAD_SIZE - 8;
+       secondary_stack =
+               (unsigned int) task_stack_page(tidle) + THREAD_SIZE - 8;
        secondary_hint = mfcr("cr31");
        secondary_ccr  = mfcr("cr18");
 
index cb7c03e..8473b6b 100644 (file)
@@ -46,3 +46,17 @@ void iounmap(void __iomem *addr)
        vunmap((void *)((unsigned long)addr & PAGE_MASK));
 }
 EXPORT_SYMBOL(iounmap);
+
+pgprot_t phys_mem_access_prot(struct file *file, unsigned long pfn,
+                             unsigned long size, pgprot_t vma_prot)
+{
+       if (!pfn_valid(pfn)) {
+               vma_prot.pgprot |= _PAGE_SO;
+               return pgprot_noncached(vma_prot);
+       } else if (file->f_flags & O_SYNC) {
+               return pgprot_noncached(vma_prot);
+       }
+
+       return vma_prot;
+}
+EXPORT_SYMBOL(phys_mem_access_prot);
index 4003ddc..f801f37 100644 (file)
@@ -37,8 +37,6 @@ libs-y        += arch/$(ARCH)/lib/
 
 boot := arch/h8300/boot
 
-archmrproper:
-
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
index cd400d3..961c1dc 100644 (file)
@@ -40,6 +40,7 @@ generic-y += preempt.h
 generic-y += scatterlist.h
 generic-y += sections.h
 generic-y += serial.h
+generic-y += shmparam.h
 generic-y += sizes.h
 generic-y += spinlock.h
 generic-y += timex.h
index 47c4da3..b25fd42 100644 (file)
@@ -30,6 +30,7 @@ generic-y += rwsem.h
 generic-y += sections.h
 generic-y += segment.h
 generic-y += serial.h
+generic-y += shmparam.h
 generic-y += sizes.h
 generic-y += topology.h
 generic-y += trace_clock.h
index 320d86f..171290f 100644 (file)
@@ -16,8 +16,6 @@ KBUILD_DEFCONFIG := generic_defconfig
 NM := $(CROSS_COMPILE)nm -B
 READELF := $(CROSS_COMPILE)readelf
 
-export AWK
-
 CHECKFLAGS     += -D__ia64=1 -D__ia64__=1 -D_LP64 -D__LP64__
 
 OBJCOPYFLAGS   := --strip-all
index 3804935..40712e4 100644 (file)
@@ -155,18 +155,22 @@ out:
 static int __init nfhd_init(void)
 {
        u32 blocks, bsize;
+       int ret;
        int i;
 
        nfhd_id = nf_get_id("XHDI");
        if (!nfhd_id)
                return -ENODEV;
 
-       major_num = register_blkdev(major_num, "nfhd");
-       if (major_num <= 0) {
+       ret = register_blkdev(major_num, "nfhd");
+       if (ret < 0) {
                pr_warn("nfhd: unable to get major number\n");
-               return major_num;
+               return ret;
        }
 
+       if (!major_num)
+               major_num = ret;
+
        for (i = NFHD_DEV_OFFSET; i < 24; i++) {
                if (nfhd_get_capacity(i, 0, &blocks, &bsize))
                        continue;
index 9f1dd26..95f8f63 100644 (file)
@@ -20,6 +20,7 @@ generic-y += mm-arch-hooks.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += sections.h
+generic-y += shmparam.h
 generic-y += spinlock.h
 generic-y += topology.h
 generic-y += trace_clock.h
index 9c7d1d2..791cc8d 100644 (file)
@@ -26,6 +26,7 @@ generic-y += parport.h
 generic-y += percpu.h
 generic-y += preempt.h
 generic-y += serial.h
+generic-y += shmparam.h
 generic-y += syscalls.h
 generic-y += topology.h
 generic-y += trace_clock.h
index 7872907..a84c24d 100644 (file)
@@ -1403,6 +1403,21 @@ config LOONGSON3_ENHANCEMENT
          please say 'N' here. If you want a high-performance kernel to run on
          new Loongson 3 machines only, please say 'Y' here.
 
+config CPU_LOONGSON3_WORKAROUNDS
+       bool "Old Loongson 3 LLSC Workarounds"
+       default y if SMP
+       depends on CPU_LOONGSON3
+       help
+         Loongson 3 processors have the llsc issues which require workarounds.
+         Without workarounds the system may hang unexpectedly.
+
+         Newer Loongson 3 will fix these issues and no workarounds are needed.
+         The workarounds have no significant side effect on them but may
+         decrease the performance of the system so this option should be
+         disabled unless the kernel is intended to be run on old systems.
+
+         If unsure, please say Y.
+
 config CPU_LOONGSON2E
        bool "Loongson 2E"
        depends on SYS_HAS_CPU_LOONGSON2E
@@ -3155,6 +3170,7 @@ config MIPS32_O32
 config MIPS32_N32
        bool "Kernel support for n32 binaries"
        depends on 64BIT
+       select ARCH_WANT_COMPAT_IPC_PARSE_VERSION
        select COMPAT
        select MIPS32_COMPAT
        select SYSVIPC_COMPAT if SYSVIPC
index 6054d49..fe37735 100644 (file)
@@ -173,6 +173,31 @@ void __init plat_mem_setup(void)
        pm_power_off = bcm47xx_machine_halt;
 }
 
+#ifdef CONFIG_BCM47XX_BCMA
+static struct device * __init bcm47xx_setup_device(void)
+{
+       struct device *dev;
+       int err;
+
+       dev = kzalloc(sizeof(*dev), GFP_KERNEL);
+       if (!dev)
+               return NULL;
+
+       err = dev_set_name(dev, "bcm47xx_soc");
+       if (err) {
+               pr_err("Failed to set SoC device name: %d\n", err);
+               kfree(dev);
+               return NULL;
+       }
+
+       err = dma_coerce_mask_and_coherent(dev, DMA_BIT_MASK(32));
+       if (err)
+               pr_err("Failed to set SoC DMA mask: %d\n", err);
+
+       return dev;
+}
+#endif
+
 /*
  * This finishes bus initialization doing things that were not possible without
  * kmalloc. Make sure to call it late enough (after mm_init).
@@ -183,6 +208,10 @@ void __init bcm47xx_bus_setup(void)
        if (bcm47xx_bus_type == BCM47XX_BUS_TYPE_BCMA) {
                int err;
 
+               bcm47xx_bus.bcma.dev = bcm47xx_setup_device();
+               if (!bcm47xx_bus.bcma.dev)
+                       panic("Failed to setup SoC device\n");
+
                err = bcma_host_soc_init(&bcm47xx_bus.bcma);
                if (err)
                        panic("Failed to initialize BCMA bus (err %d)", err);
@@ -235,6 +264,8 @@ static int __init bcm47xx_register_bus_complete(void)
 #endif
 #ifdef CONFIG_BCM47XX_BCMA
        case BCM47XX_BUS_TYPE_BCMA:
+               if (device_register(bcm47xx_bus.bcma.dev))
+                       pr_err("Failed to register SoC device\n");
                bcma_bus_register(&bcm47xx_bus.bcma.bus);
                break;
 #endif
index 50cff3c..4f7b1fa 100644 (file)
@@ -76,7 +76,7 @@
        status = "okay";
 
        pinctrl-names = "default";
-       pinctrl-0 = <&pins_uart2>;
+       pinctrl-0 = <&pins_uart3>;
 };
 
 &uart4 {
                bias-disable;
        };
 
-       pins_uart2: uart2 {
-               function = "uart2";
-               groups = "uart2-data", "uart2-hwflow";
+       pins_uart3: uart3 {
+               function = "uart3";
+               groups = "uart3-data", "uart3-hwflow";
                bias-disable;
        };
 
index 6fb16fd..2beb78a 100644 (file)
                #dma-cells = <2>;
 
                interrupt-parent = <&intc>;
-               interrupts = <29>;
+               interrupts = <20>;
 
                clocks = <&cgu JZ4740_CLK_DMA>;
 
index 2152b7b..cc8dbea 100644 (file)
                interrupts = <0>;
        };
 
-       axi_i2c: i2c@10A00000 {
+       axi_i2c: i2c@10a00000 {
            compatible = "xlnx,xps-iic-2.00.a";
            interrupt-parent = <&axi_intc>;
            interrupts = <4>;
-           reg = < 0x10A00000 0x10000 >;
+           reg = < 0x10a00000 0x10000 >;
            clocks = <&ext>;
            xlnx,clk-freq = <0x5f5e100>;
            xlnx,family = "Artix7";
            #address-cells = <1>;
            #size-cells = <0>;
 
-           ad7420@4B {
+           ad7420@4b {
                compatible = "adi,adt7420";
-               reg = <0x4B>;
+               reg = <0x4b>;
            };
        } ;
 };
index 2c79ab5..8bf43c5 100644 (file)
@@ -98,7 +98,7 @@ static void octeon_kexec_smp_down(void *ignored)
        "       sync                                            \n"
        "       synci   ($0)                                    \n");
 
-       relocated_kexec_smp_wait(NULL);
+       kexec_reboot();
 }
 #endif
 
index 4e4ec77..6f981af 100644 (file)
@@ -66,6 +66,7 @@ CONFIG_SERIAL_8250_CONSOLE=y
 # CONFIG_SERIAL_8250_PCI is not set
 CONFIG_SERIAL_8250_NR_UARTS=1
 CONFIG_SERIAL_8250_RUNTIME_UARTS=1
+CONFIG_SERIAL_OF_PLATFORM=y
 CONFIG_SERIAL_AR933X=y
 CONFIG_SERIAL_AR933X_CONSOLE=y
 # CONFIG_HW_RANDOM is not set
index 43fcd35..9409629 100644 (file)
@@ -58,6 +58,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v)                             \
        if (kernel_uses_llsc) {                                               \
                int temp;                                                     \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
@@ -85,6 +86,7 @@ static __inline__ int atomic_##op##_return_relaxed(int i, atomic_t * v)             \
        if (kernel_uses_llsc) {                                               \
                int temp;                                                     \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
@@ -118,6 +120,7 @@ static __inline__ int atomic_fetch_##op##_relaxed(int i, atomic_t * v)            \
        if (kernel_uses_llsc) {                                               \
                int temp;                                                     \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
@@ -256,6 +259,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v)                      \
        if (kernel_uses_llsc) {                                               \
                long temp;                                                    \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
@@ -283,6 +287,7 @@ static __inline__ long atomic64_##op##_return_relaxed(long i, atomic64_t * v) \
        if (kernel_uses_llsc) {                                               \
                long temp;                                                    \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
@@ -316,6 +321,7 @@ static __inline__ long atomic64_fetch_##op##_relaxed(long i, atomic64_t * v)  \
        if (kernel_uses_llsc) {                                               \
                long temp;                                                    \
                                                                              \
+               loongson_llsc_mb();                                           \
                __asm__ __volatile__(                                         \
                "       .set    push                                    \n"   \
                "       .set    "MIPS_ISA_LEVEL"                        \n"   \
index a5eb1bb..b7f6ac5 100644 (file)
 #define __smp_mb__before_atomic()      __smp_mb__before_llsc()
 #define __smp_mb__after_atomic()       smp_llsc_mb()
 
+/*
+ * Some Loongson 3 CPUs have a bug wherein execution of a memory access (load,
+ * store or pref) in between an ll & sc can cause the sc instruction to
+ * erroneously succeed, breaking atomicity. Whilst it's unusual to write code
+ * containing such sequences, this bug bites harder than we might otherwise
+ * expect due to reordering & speculation:
+ *
+ * 1) A memory access appearing prior to the ll in program order may actually
+ *    be executed after the ll - this is the reordering case.
+ *
+ *    In order to avoid this we need to place a memory barrier (ie. a sync
+ *    instruction) prior to every ll instruction, in between it & any earlier
+ *    memory access instructions. Many of these cases are already covered by
+ *    smp_mb__before_llsc() but for the remaining cases, typically ones in
+ *    which multiple CPUs may operate on a memory location but ordering is not
+ *    usually guaranteed, we use loongson_llsc_mb() below.
+ *
+ *    This reordering case is fixed by 3A R2 CPUs, ie. 3A2000 models and later.
+ *
+ * 2) If a conditional branch exists between an ll & sc with a target outside
+ *    of the ll-sc loop, for example an exit upon value mismatch in cmpxchg()
+ *    or similar, then misprediction of the branch may allow speculative
+ *    execution of memory accesses from outside of the ll-sc loop.
+ *
+ *    In order to avoid this we need a memory barrier (ie. a sync instruction)
+ *    at each affected branch target, for which we also use loongson_llsc_mb()
+ *    defined below.
+ *
+ *    This case affects all current Loongson 3 CPUs.
+ */
+#ifdef CONFIG_CPU_LOONGSON3_WORKAROUNDS /* Loongson-3's LLSC workaround */
+#define loongson_llsc_mb()     __asm__ __volatile__(__WEAK_LLSC_MB : : :"memory")
+#else
+#define loongson_llsc_mb()     do { } while (0)
+#endif
+
 #include <asm-generic/barrier.h>
 
 #endif /* __ASM_BARRIER_H */
index c467595..830c93a 100644 (file)
@@ -69,6 +69,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
                : "ir" (1UL << bit), GCC_OFF_SMALL_ASM() (*m));
 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
        } else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
+               loongson_llsc_mb();
                do {
                        __asm__ __volatile__(
                        "       " __LL "%0, %1          # set_bit       \n"
@@ -79,6 +80,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
                } while (unlikely(!temp));
 #endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
        } else if (kernel_uses_llsc) {
+               loongson_llsc_mb();
                do {
                        __asm__ __volatile__(
                        "       .set    push                            \n"
@@ -123,6 +125,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
                : "ir" (~(1UL << bit)));
 #if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
        } else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
+               loongson_llsc_mb();
                do {
                        __asm__ __volatile__(
                        "       " __LL "%0, %1          # clear_bit     \n"
@@ -133,6 +136,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
                } while (unlikely(!temp));
 #endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
        } else if (kernel_uses_llsc) {
+               loongson_llsc_mb();
                do {
                        __asm__ __volatile__(
                        "       .set    push                            \n"
@@ -193,6 +197,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
                unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
                unsigned long temp;
 
+               loongson_llsc_mb();
                do {
                        __asm__ __volatile__(
                        "       .set    push                            \n"
index c14d798..b83b039 100644 (file)
@@ -50,6 +50,7 @@
                  "i" (-EFAULT)                                         \
                : "memory");                                            \
        } else if (cpu_has_llsc) {                                      \
+               loongson_llsc_mb();                                     \
                __asm__ __volatile__(                                   \
                "       .set    push                            \n"     \
                "       .set    noat                            \n"     \
@@ -163,6 +164,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
                  "i" (-EFAULT)
                : "memory");
        } else if (cpu_has_llsc) {
+               loongson_llsc_mb();
                __asm__ __volatile__(
                "# futex_atomic_cmpxchg_inatomic                        \n"
                "       .set    push                                    \n"
@@ -192,6 +194,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
                : GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
                  "i" (-EFAULT)
                : "memory");
+               loongson_llsc_mb();
        } else
                return -ENOSYS;
 
index c6b63a4..6dd8ad2 100644 (file)
@@ -18,8 +18,6 @@
 #define INT_NUM_EXTRA_START            (INT_NUM_IM4_IRL0 + 32)
 #define INT_NUM_IM_OFFSET              (INT_NUM_IM1_IRL0 - INT_NUM_IM0_IRL0)
 
-#define MIPS_CPU_TIMER_IRQ                     7
-
 #define MAX_IM                 5
 
 #endif /* _FALCON_IRQ__ */
index 1410763..0b42421 100644 (file)
@@ -19,8 +19,6 @@
 
 #define LTQ_DMA_CH0_INT                (INT_NUM_IM2_IRL0)
 
-#define MIPS_CPU_TIMER_IRQ     7
-
 #define MAX_IM                 5
 
 #endif
index 57933fc..910851c 100644 (file)
@@ -228,6 +228,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
                        : [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp)
                        : [global] "r" (page_global));
                } else if (kernel_uses_llsc) {
+                       loongson_llsc_mb();
                        __asm__ __volatile__ (
                        "       .set    push                            \n"
                        "       .set    "MIPS_ISA_ARCH_LEVEL"           \n"
@@ -242,6 +243,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
                        "       .set    pop                             \n"
                        : [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp)
                        : [global] "r" (page_global));
+                       loongson_llsc_mb();
                }
 #else /* !CONFIG_SMP */
                if (pte_none(*buddy))
index 6256d35..bedb504 100644 (file)
@@ -74,14 +74,15 @@ static int __init vdma_init(void)
                                                    get_order(VDMA_PGTBL_SIZE));
        BUG_ON(!pgtbl);
        dma_cache_wback_inv((unsigned long)pgtbl, VDMA_PGTBL_SIZE);
-       pgtbl = (VDMA_PGTBL_ENTRY *)KSEG1ADDR(pgtbl);
+       pgtbl = (VDMA_PGTBL_ENTRY *)CKSEG1ADDR((unsigned long)pgtbl);
 
        /*
         * Clear the R4030 translation table
         */
        vdma_pgtbl_init();
 
-       r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE, CPHYSADDR(pgtbl));
+       r4030_write_reg32(JAZZ_R4030_TRSTBL_BASE,
+                         CPHYSADDR((unsigned long)pgtbl));
        r4030_write_reg32(JAZZ_R4030_TRSTBL_LIM, VDMA_PGTBL_SIZE);
        r4030_write_reg32(JAZZ_R4030_TRSTBL_INV, 0);
 
index 8f5bd04..7f3f136 100644 (file)
@@ -457,5 +457,5 @@ void mips_cm_error_report(void)
        }
 
        /* reprime cause register */
-       write_gcr_error_cause(0);
+       write_gcr_error_cause(cm_error);
 }
index 6829a06..339870e 100644 (file)
@@ -371,7 +371,7 @@ static inline int is_sp_move_ins(union mips_instruction *ip, int *frame_size)
 static int get_frame_info(struct mips_frame_info *info)
 {
        bool is_mmips = IS_ENABLED(CONFIG_CPU_MICROMIPS);
-       union mips_instruction insn, *ip, *ip_end;
+       union mips_instruction insn, *ip;
        const unsigned int max_insns = 128;
        unsigned int last_insn_size = 0;
        unsigned int i;
@@ -384,10 +384,9 @@ static int get_frame_info(struct mips_frame_info *info)
        if (!ip)
                goto err;
 
-       ip_end = (void *)ip + info->func_size;
-
-       for (i = 0; i < max_insns && ip < ip_end; i++) {
+       for (i = 0; i < max_insns; i++) {
                ip = (void *)ip + last_insn_size;
+
                if (is_mmips && mm_insn_16bit(ip->halfword[0])) {
                        insn.word = ip->halfword[0] << 16;
                        last_insn_size = 2;
index f0bc331..6549499 100644 (file)
@@ -224,9 +224,11 @@ static struct irq_chip ltq_eiu_type = {
        .irq_set_type = ltq_eiu_settype,
 };
 
-static void ltq_hw_irqdispatch(int module)
+static void ltq_hw_irq_handler(struct irq_desc *desc)
 {
+       int module = irq_desc_get_irq(desc) - 2;
        u32 irq;
+       int hwirq;
 
        irq = ltq_icu_r32(module, LTQ_ICU_IM0_IOSR);
        if (irq == 0)
@@ -237,7 +239,8 @@ static void ltq_hw_irqdispatch(int module)
         * other bits might be bogus
         */
        irq = __fls(irq);
-       do_IRQ((int)irq + MIPS_CPU_IRQ_CASCADE + (INT_NUM_IM_OFFSET * module));
+       hwirq = irq + MIPS_CPU_IRQ_CASCADE + (INT_NUM_IM_OFFSET * module);
+       generic_handle_irq(irq_linear_revmap(ltq_domain, hwirq));
 
        /* if this is a EBU irq, we need to ack it or get a deadlock */
        if ((irq == LTQ_ICU_EBU_IRQ) && (module == 0) && LTQ_EBU_PCC_ISTAT)
@@ -245,49 +248,6 @@ static void ltq_hw_irqdispatch(int module)
                        LTQ_EBU_PCC_ISTAT);
 }
 
-#define DEFINE_HWx_IRQDISPATCH(x)                                      \
-       static void ltq_hw ## x ## _irqdispatch(void)                   \
-       {                                                               \
-               ltq_hw_irqdispatch(x);                                  \
-       }
-DEFINE_HWx_IRQDISPATCH(0)
-DEFINE_HWx_IRQDISPATCH(1)
-DEFINE_HWx_IRQDISPATCH(2)
-DEFINE_HWx_IRQDISPATCH(3)
-DEFINE_HWx_IRQDISPATCH(4)
-
-#if MIPS_CPU_TIMER_IRQ == 7
-static void ltq_hw5_irqdispatch(void)
-{
-       do_IRQ(MIPS_CPU_TIMER_IRQ);
-}
-#else
-DEFINE_HWx_IRQDISPATCH(5)
-#endif
-
-static void ltq_hw_irq_handler(struct irq_desc *desc)
-{
-       ltq_hw_irqdispatch(irq_desc_get_irq(desc) - 2);
-}
-
-asmlinkage void plat_irq_dispatch(void)
-{
-       unsigned int pending = read_c0_status() & read_c0_cause() & ST0_IM;
-       int irq;
-
-       if (!pending) {
-               spurious_interrupt();
-               return;
-       }
-
-       pending >>= CAUSEB_IP;
-       while (pending) {
-               irq = fls(pending) - 1;
-               do_IRQ(MIPS_CPU_IRQ_BASE + irq);
-               pending &= ~BIT(irq);
-       }
-}
-
 static int icu_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw)
 {
        struct irq_chip *chip = &ltq_irq_type;
@@ -343,38 +303,13 @@ int __init icu_of_init(struct device_node *node, struct device_node *parent)
        for (i = 0; i < MAX_IM; i++)
                irq_set_chained_handler(i + 2, ltq_hw_irq_handler);
 
-       if (cpu_has_vint) {
-               pr_info("Setting up vectored interrupts\n");
-               set_vi_handler(2, ltq_hw0_irqdispatch);
-               set_vi_handler(3, ltq_hw1_irqdispatch);
-               set_vi_handler(4, ltq_hw2_irqdispatch);
-               set_vi_handler(5, ltq_hw3_irqdispatch);
-               set_vi_handler(6, ltq_hw4_irqdispatch);
-               set_vi_handler(7, ltq_hw5_irqdispatch);
-       }
-
        ltq_domain = irq_domain_add_linear(node,
                (MAX_IM * INT_NUM_IM_OFFSET) + MIPS_CPU_IRQ_CASCADE,
                &irq_domain_ops, 0);
 
-#ifndef CONFIG_MIPS_MT_SMP
-       set_c0_status(IE_IRQ0 | IE_IRQ1 | IE_IRQ2 |
-               IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
-#else
-       set_c0_status(IE_SW0 | IE_SW1 | IE_IRQ0 | IE_IRQ1 |
-               IE_IRQ2 | IE_IRQ3 | IE_IRQ4 | IE_IRQ5);
-#endif
-
        /* tell oprofile which irq to use */
        ltq_perfcount_irq = irq_create_mapping(ltq_domain, LTQ_PERF_IRQ);
 
-       /*
-        * if the timer irq is not one of the mips irqs we need to
-        * create a mapping
-        */
-       if (MIPS_CPU_TIMER_IRQ != 7)
-               irq_create_mapping(ltq_domain, MIPS_CPU_TIMER_IRQ);
-
        /* the external interrupts are optional and xway only */
        eiu_node = of_find_compatible_node(NULL, NULL, "lantiq,eiu-xway");
        if (eiu_node && !of_address_to_resource(eiu_node, 0, &res)) {
@@ -411,7 +346,7 @@ EXPORT_SYMBOL_GPL(get_c0_perfcount_int);
 
 unsigned int get_c0_compare_int(void)
 {
-       return MIPS_CPU_TIMER_IRQ;
+       return CP0_LEGACY_COMPARE_IRQ;
 }
 
 static struct of_device_id __initdata of_irq_ids[] = {
index 982859f..5e6a1a4 100644 (file)
@@ -129,9 +129,9 @@ ltq_dma_alloc(struct ltq_dma_channel *ch)
        unsigned long flags;
 
        ch->desc = 0;
-       ch->desc_base = dma_zalloc_coherent(ch->dev,
-                               LTQ_DESC_NUM * LTQ_DESC_SIZE,
-                               &ch->phys, GFP_ATOMIC);
+       ch->desc_base = dma_alloc_coherent(ch->dev,
+                                          LTQ_DESC_NUM * LTQ_DESC_SIZE,
+                                          &ch->phys, GFP_ATOMIC);
 
        spin_lock_irqsave(&ltq_dma_lock, flags);
        ltq_dma_w32(ch->nr, LTQ_DMA_CS);
index 0fce460..c1a4d4d 100644 (file)
@@ -23,6 +23,29 @@ ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS
 endif
 
 cflags-$(CONFIG_CPU_LOONGSON3) += -Wa,--trap
+
+#
+# Some versions of binutils, not currently mainline as of 2019/02/04, support
+# an -mfix-loongson3-llsc flag which emits a sync prior to each ll instruction
+# to work around a CPU bug (see loongson_llsc_mb() in asm/barrier.h for a
+# description).
+#
+# We disable this in order to prevent the assembler meddling with the
+# instruction that labels refer to, ie. if we label an ll instruction:
+#
+# 1: ll v0, 0(a0)
+#
+# ...then with the assembler fix applied the label may actually point at a sync
+# instruction inserted by the assembler, and if we were using the label in an
+# exception table the table would no longer contain the address of the ll
+# instruction.
+#
+# Avoid this by explicitly disabling that assembler behaviour. If upstream
+# binutils does not merge support for the flag then we can revisit & remove
+# this later - for now it ensures vendor toolchains don't cause problems.
+#
+cflags-$(CONFIG_CPU_LOONGSON3) += $(call as-option,-Wa$(comma)-mno-fix-loongson3-llsc,)
+
 #
 # binutils from v2.25 on and gcc starting from v4.9.0 treat -march=loongson3a
 # as MIPS64 R2; older versions as just R1.  This leaves the possibility open
index a60715e..b26892c 100644 (file)
@@ -59,7 +59,12 @@ static void loongson_poweroff(void)
 {
 #ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
        mach_prepare_shutdown();
-       unreachable();
+
+       /*
+        * It needs a wait loop here, but mips/kernel/reset.c already calls
+        * a generic delay loop, machine_hang(), so simply return.
+        */
+       return;
 #else
        void (*fw_poweroff)(void) = (void *)loongson_sysconf.poweroff_addr;
 
index 37b1cb2..65b6e85 100644 (file)
@@ -932,6 +932,8 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
                 * to mimic that here by taking a load/istream page
                 * fault.
                 */
+               if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
+                       uasm_i_sync(p, 0);
                UASM_i_LA(p, ptr, (unsigned long)tlb_do_page_fault_0);
                uasm_i_jr(p, ptr);
 
@@ -1646,6 +1648,8 @@ static void
 iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
 {
 #ifdef CONFIG_SMP
+       if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
+               uasm_i_sync(p, 0);
 # ifdef CONFIG_PHYS_ADDR_T_64BIT
        if (cpu_has_64bits)
                uasm_i_lld(p, pte, 0, ptr);
@@ -2259,6 +2263,8 @@ static void build_r4000_tlb_load_handler(void)
 #endif
 
        uasm_l_nopage_tlbl(&l, p);
+       if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
+               uasm_i_sync(&p, 0);
        build_restore_work_registers(&p);
 #ifdef CONFIG_CPU_MICROMIPS
        if ((unsigned long)tlb_do_page_fault_0 & 1) {
@@ -2313,6 +2319,8 @@ static void build_r4000_tlb_store_handler(void)
 #endif
 
        uasm_l_nopage_tlbs(&l, p);
+       if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
+               uasm_i_sync(&p, 0);
        build_restore_work_registers(&p);
 #ifdef CONFIG_CPU_MICROMIPS
        if ((unsigned long)tlb_do_page_fault_1 & 1) {
@@ -2368,6 +2376,8 @@ static void build_r4000_tlb_modify_handler(void)
 #endif
 
        uasm_l_nopage_tlbm(&l, p);
+       if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
+               uasm_i_sync(&p, 0);
        build_restore_work_registers(&p);
 #ifdef CONFIG_CPU_MICROMIPS
        if ((unsigned long)tlb_do_page_fault_1 & 1) {
index b16710a..76e9bf8 100644 (file)
@@ -79,8 +79,6 @@ enum reg_val_type {
        REG_64BIT_32BIT,
        /* 32-bit compatible, need truncation for 64-bit ops. */
        REG_32BIT,
-       /* 32-bit zero extended. */
-       REG_32BIT_ZERO_EX,
        /* 32-bit no sign/zero extension needed. */
        REG_32BIT_POS
 };
@@ -343,12 +341,15 @@ static int build_int_epilogue(struct jit_ctx *ctx, int dest_reg)
        const struct bpf_prog *prog = ctx->skf;
        int stack_adjust = ctx->stack_size;
        int store_offset = stack_adjust - 8;
+       enum reg_val_type td;
        int r0 = MIPS_R_V0;
 
-       if (dest_reg == MIPS_R_RA &&
-           get_reg_val_type(ctx, prog->len, BPF_REG_0) == REG_32BIT_ZERO_EX)
+       if (dest_reg == MIPS_R_RA) {
                /* Don't let zero extended value escape. */
-               emit_instr(ctx, sll, r0, r0, 0);
+               td = get_reg_val_type(ctx, prog->len, BPF_REG_0);
+               if (td == REG_64BIT)
+                       emit_instr(ctx, sll, r0, r0, 0);
+       }
 
        if (ctx->flags & EBPF_SAVE_RA) {
                emit_instr(ctx, ld, MIPS_R_RA, store_offset, MIPS_R_SP);
@@ -692,7 +693,7 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
                if (dst < 0)
                        return dst;
                td = get_reg_val_type(ctx, this_idx, insn->dst_reg);
-               if (td == REG_64BIT || td == REG_32BIT_ZERO_EX) {
+               if (td == REG_64BIT) {
                        /* sign extend */
                        emit_instr(ctx, sll, dst, dst, 0);
                }
@@ -707,7 +708,7 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
                if (dst < 0)
                        return dst;
                td = get_reg_val_type(ctx, this_idx, insn->dst_reg);
-               if (td == REG_64BIT || td == REG_32BIT_ZERO_EX) {
+               if (td == REG_64BIT) {
                        /* sign extend */
                        emit_instr(ctx, sll, dst, dst, 0);
                }
@@ -721,7 +722,7 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
                if (dst < 0)
                        return dst;
                td = get_reg_val_type(ctx, this_idx, insn->dst_reg);
-               if (td == REG_64BIT || td == REG_32BIT_ZERO_EX)
+               if (td == REG_64BIT)
                        /* sign extend */
                        emit_instr(ctx, sll, dst, dst, 0);
                if (insn->imm == 1) {
@@ -860,13 +861,13 @@ static int build_one_insn(const struct bpf_insn *insn, struct jit_ctx *ctx,
                if (src < 0 || dst < 0)
                        return -EINVAL;
                td = get_reg_val_type(ctx, this_idx, insn->dst_reg);
-               if (td == REG_64BIT || td == REG_32BIT_ZERO_EX) {
+               if (td == REG_64BIT) {
                        /* sign extend */
                        emit_instr(ctx, sll, dst, dst, 0);
                }
                did_move = false;
                ts = get_reg_val_type(ctx, this_idx, insn->src_reg);
-               if (ts == REG_64BIT || ts == REG_32BIT_ZERO_EX) {
+               if (ts == REG_64BIT) {
                        int tmp_reg = MIPS_R_AT;
 
                        if (bpf_op == BPF_MOV) {
@@ -1254,8 +1255,7 @@ jeq_common:
                if (insn->imm == 64 && td == REG_32BIT)
                        emit_instr(ctx, dinsu, dst, MIPS_R_ZERO, 32, 32);
 
-               if (insn->imm != 64 &&
-                   (td == REG_64BIT || td == REG_32BIT_ZERO_EX)) {
+               if (insn->imm != 64 && td == REG_64BIT) {
                        /* sign extend */
                        emit_instr(ctx, sll, dst, dst, 0);
                }
index 2a5bb84..288b58b 100644 (file)
@@ -369,7 +369,9 @@ int __init octeon_msi_initialize(void)
        int irq;
        struct irq_chip *msi;
 
-       if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) {
+       if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_INVALID) {
+               return 0;
+       } else if (octeon_dma_bar_type == OCTEON_DMA_BAR_TYPE_PCIE) {
                msi_rcv_reg[0] = CVMX_PEXP_NPEI_MSI_RCV0;
                msi_rcv_reg[1] = CVMX_PEXP_NPEI_MSI_RCV1;
                msi_rcv_reg[2] = CVMX_PEXP_NPEI_MSI_RCV2;
index 5017d58..fc29b85 100644 (file)
@@ -568,6 +568,11 @@ static int __init octeon_pci_setup(void)
        if (octeon_has_feature(OCTEON_FEATURE_PCIE))
                return 0;
 
+       if (!octeon_is_pci_host()) {
+               pr_notice("Not in host mode, PCI Controller not initialized\n");
+               return 0;
+       }
+
        /* Point pcibios_map_irq() to the PCI version of it */
        octeon_pcibios_map_irq = octeon_pci_pcibios_map_irq;
 
@@ -579,11 +584,6 @@ static int __init octeon_pci_setup(void)
        else
                octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_BIG;
 
-       if (!octeon_is_pci_host()) {
-               pr_notice("Not in host mode, PCI Controller not initialized\n");
-               return 0;
-       }
-
        /* PCI I/O and PCI MEM values */
        set_io_port_base(OCTEON_PCI_IOSPACE_BASE);
        ioport_resource.start = 0;
index f6fd340..0ede4de 100644 (file)
@@ -8,6 +8,7 @@ ccflags-vdso := \
        $(filter -E%,$(KBUILD_CFLAGS)) \
        $(filter -mmicromips,$(KBUILD_CFLAGS)) \
        $(filter -march=%,$(KBUILD_CFLAGS)) \
+       $(filter -m%-float,$(KBUILD_CFLAGS)) \
        -D__VDSO__
 
 ifdef CONFIG_CC_IS_CLANG
@@ -129,7 +130,7 @@ $(obj)/%-o32.o: $(src)/%.c FORCE
        $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)
 
-$(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := -mabi=32
+$(obj)/vdso-o32.lds: KBUILD_CPPFLAGS := $(ccflags-vdso) -mabi=32
 $(obj)/vdso-o32.lds: $(src)/vdso.lds.S FORCE
        $(call if_changed_dep,cpp_lds_S)
 
@@ -169,7 +170,7 @@ $(obj)/%-n32.o: $(src)/%.c FORCE
        $(call cmd,force_checksrc)
        $(call if_changed_rule,cc_o_c)
 
-$(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := -mabi=n32
+$(obj)/vdso-n32.lds: KBUILD_CPPFLAGS := $(ccflags-vdso) -mabi=n32
 $(obj)/vdso-n32.lds: $(src)/vdso.lds.S FORCE
        $(call if_changed_dep,cpp_lds_S)
 
index 0a935c1..ac34828 100644 (file)
@@ -3,9 +3,6 @@ OBJCOPYFLAGS    := -O binary -R .note -R .note.gnu.build-id -R .comment -S
 
 KBUILD_DEFCONFIG := defconfig
 
-comma = ,
-
-
 ifdef CONFIG_FUNCTION_TRACER
 arch-y += -malways-save-lp -mno-relax
 endif
@@ -54,8 +51,6 @@ endif
 boot := arch/nds32/boot
 core-y += $(boot)/dts/
 
-.PHONY: FORCE
-
 Image: vmlinux
        $(Q)$(MAKE) $(build)=$(boot) $(boot)/$@
 
@@ -68,9 +63,6 @@ prepare: vdso_prepare
 vdso_prepare: prepare0
        $(Q)$(MAKE) $(build)=arch/nds32/kernel/vdso include/generated/vdso-offsets.h
 
-CLEAN_FILES += include/asm-nds32/constants.h*
-
-# We use MRPROPER_FILES and CLEAN_FILES now
 archclean:
        $(Q)$(MAKE) $(clean)=$(boot)
 
index 70e06d3..bf10141 100644 (file)
@@ -20,7 +20,6 @@
 KBUILD_DEFCONFIG := or1ksim_defconfig
 
 OBJCOPYFLAGS    := -O binary -R .note -R .comment -S
-LDFLAGS_vmlinux :=
 LIBGCC                 := $(shell $(CC) $(KBUILD_CFLAGS) -print-libgcc-file-name)
 
 KBUILD_CFLAGS  += -pipe -ffixed-r10 -D__linux__
@@ -50,5 +49,3 @@ else
 BUILTIN_DTB := n
 endif
 core-$(BUILTIN_DTB) += arch/openrisc/boot/dts/
-
-all: vmlinux
index eb87cd8..1f04844 100644 (file)
@@ -34,6 +34,7 @@ generic-y += qrwlock_types.h
 generic-y += qrwlock.h
 generic-y += sections.h
 generic-y += segment.h
+generic-y += shmparam.h
 generic-y += string.h
 generic-y += switch_to.h
 generic-y += topology.h
index bc8191a..a44682c 100644 (file)
 /* Ensure that addr is below task's addr_limit */
 #define __addr_ok(addr) ((unsigned long) addr < get_fs())
 
-#define access_ok(addr, size) \
-       __range_ok((unsigned long)addr, (unsigned long)size)
+#define access_ok(addr, size)                                          \
+({                                                                     \
+       unsigned long __ao_addr = (unsigned long)(addr);                \
+       unsigned long __ao_size = (unsigned long)(size);                \
+       __range_ok(__ao_addr, __ao_size);                               \
+})
 
 /*
  * These are the main single-value transfer routines.  They automatically
index 2582df1..0964c23 100644 (file)
@@ -308,15 +308,29 @@ long compat_arch_ptrace(struct task_struct *child, compat_long_t request,
 
 long do_syscall_trace_enter(struct pt_regs *regs)
 {
-       if (test_thread_flag(TIF_SYSCALL_TRACE) &&
-           tracehook_report_syscall_entry(regs)) {
+       if (test_thread_flag(TIF_SYSCALL_TRACE)) {
+               int rc = tracehook_report_syscall_entry(regs);
+
                /*
-                * Tracing decided this syscall should not happen or the
-                * debugger stored an invalid system call number. Skip
-                * the system call and the system call restart handling.
+                * As tracesys_next does not set %r28 to -ENOSYS
+                * when %r20 is set to -1, initialize it here.
                 */
-               regs->gr[20] = -1UL;
-               goto out;
+               regs->gr[28] = -ENOSYS;
+
+               if (rc) {
+                       /*
+                        * A nonzero return code from
+                        * tracehook_report_syscall_entry() tells us
+                        * to prevent the syscall execution.  Skip
+                        * the syscall call and the syscall restart handling.
+                        *
+                        * Note that the tracer may also just change
+                        * regs->gr[20] to an invalid syscall number,
+                        * that is handled by tracesys_next.
+                        */
+                       regs->gr[20] = -1UL;
+                       return -1;
+               }
        }
 
        /* Do the secure computing check after ptrace. */
@@ -340,7 +354,6 @@ long do_syscall_trace_enter(struct pt_regs *regs)
                        regs->gr[24] & 0xffffffff,
                        regs->gr[23] & 0xffffffff);
 
-out:
        /*
         * Sign extend the syscall number to 64bit since it may have been
         * modified by a compat ptrace call
index 2e6ada2..d8c8d7c 100644 (file)
@@ -904,7 +904,7 @@ static inline int pud_none(pud_t pud)
 
 static inline int pud_present(pud_t pud)
 {
-       return (pud_raw(pud) & cpu_to_be64(_PAGE_PRESENT));
+       return !!(pud_raw(pud) & cpu_to_be64(_PAGE_PRESENT));
 }
 
 extern struct page *pud_page(pud_t pud);
@@ -951,7 +951,7 @@ static inline int pgd_none(pgd_t pgd)
 
 static inline int pgd_present(pgd_t pgd)
 {
-       return (pgd_raw(pgd) & cpu_to_be64(_PAGE_PRESENT));
+       return !!(pgd_raw(pgd) & cpu_to_be64(_PAGE_PRESENT));
 }
 
 static inline pte_t pgd_pte(pgd_t pgd)
@@ -1258,21 +1258,13 @@ extern pmd_t pmdp_invalidate(struct vm_area_struct *vma, unsigned long address,
 
 #define pmd_move_must_withdraw pmd_move_must_withdraw
 struct spinlock;
-static inline int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
-                                        struct spinlock *old_pmd_ptl,
-                                        struct vm_area_struct *vma)
-{
-       if (radix_enabled())
-               return false;
-       /*
-        * Archs like ppc64 use pgtable to store per pmd
-        * specific information. So when we switch the pmd,
-        * we should also withdraw and deposit the pgtable
-        */
-       return true;
-}
-
-
+extern int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
+                                 struct spinlock *old_pmd_ptl,
+                                 struct vm_area_struct *vma);
+/*
+ * Hash translation mode use the deposited table to store hash pte
+ * slot information.
+ */
 #define arch_needs_pgtable_deposit arch_needs_pgtable_deposit
 static inline bool arch_needs_pgtable_deposit(void)
 {
index ff91192..f599064 100644 (file)
@@ -47,6 +47,7 @@ enum perf_event_powerpc_regs {
        PERF_REG_POWERPC_DAR,
        PERF_REG_POWERPC_DSISR,
        PERF_REG_POWERPC_SIER,
+       PERF_REG_POWERPC_MMCRA,
        PERF_REG_POWERPC_MAX,
 };
 #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */
index 57deb1e..20cc816 100644 (file)
@@ -852,11 +852,12 @@ start_here:
 
        /* set up the PTE pointers for the Abatron bdiGDB.
        */
-       tovirt(r6,r6)
        lis     r5, abatron_pteptrs@h
        ori     r5, r5, abatron_pteptrs@l
        stw     r5, 0xf0(0)     /* Must match your Abatron config file */
        tophys(r5,r5)
+       lis     r6, swapper_pg_dir@h
+       ori     r6, r6, swapper_pg_dir@l
        stw     r6, 0(r5)
 
 /* Now turn on the MMU for real! */
index bd5e683..6794466 100644 (file)
@@ -755,11 +755,12 @@ SYSCALL_DEFINE0(rt_sigreturn)
                if (restore_tm_sigcontexts(current, &uc->uc_mcontext,
                                           &uc_transact->uc_mcontext))
                        goto badframe;
-       }
+       } else
 #endif
-       /* Fall through, for non-TM restore */
-       if (!MSR_TM_ACTIVE(msr)) {
+       {
                /*
+                * Fall through, for non-TM restore
+                *
                 * Unset MSR[TS] on the thread regs since MSR from user
                 * context does not have MSR active, and recheckpoint was
                 * not called since restore_tm_sigcontexts() was not called
index 29746dc..517662a 100644 (file)
@@ -967,13 +967,6 @@ out:
 }
 #endif /* CONFIG_FUNCTION_GRAPH_TRACER */
 
-#if defined(CONFIG_FTRACE_SYSCALLS) && defined(CONFIG_PPC64)
-unsigned long __init arch_syscall_addr(int nr)
-{
-       return sys_call_table[nr*2];
-}
-#endif /* CONFIG_FTRACE_SYSCALLS && CONFIG_PPC64 */
-
 #ifdef PPC64_ELF_ABI_v1
 char *arch_ftrace_match_adjust(char *str, const char *search)
 {
index f3c31f5..ecd3156 100644 (file)
@@ -400,3 +400,25 @@ void arch_report_meminfo(struct seq_file *m)
                   atomic_long_read(&direct_pages_count[MMU_PAGE_1G]) << 20);
 }
 #endif /* CONFIG_PROC_FS */
+
+/*
+ * For hash translation mode, we use the deposited table to store hash slot
+ * information and they are stored at PTRS_PER_PMD offset from related pmd
+ * location. Hence a pmd move requires deposit and withdraw.
+ *
+ * For radix translation with split pmd ptl, we store the deposited table in the
+ * pmd page. Hence if we have different pmd page we need to withdraw during pmd
+ * move.
+ *
+ * With hash we use deposited table always irrespective of anon or not.
+ * With radix we use deposited table only for anonymous mapping.
+ */
+int pmd_move_must_withdraw(struct spinlock *new_pmd_ptl,
+                          struct spinlock *old_pmd_ptl,
+                          struct vm_area_struct *vma)
+{
+       if (radix_enabled())
+               return (new_pmd_ptl != old_pmd_ptl) && vma_is_anonymous(vma);
+
+       return true;
+}
index 5c36b3a..3349f3f 100644 (file)
@@ -70,6 +70,7 @@ static unsigned int pt_regs_offset[PERF_REG_POWERPC_MAX] = {
        PT_REGS_OFFSET(PERF_REG_POWERPC_DAR, dar),
        PT_REGS_OFFSET(PERF_REG_POWERPC_DSISR, dsisr),
        PT_REGS_OFFSET(PERF_REG_POWERPC_SIER, dar),
+       PT_REGS_OFFSET(PERF_REG_POWERPC_MMCRA, dsisr),
 };
 
 u64 perf_reg_value(struct pt_regs *regs, int idx)
@@ -83,6 +84,11 @@ u64 perf_reg_value(struct pt_regs *regs, int idx)
            !is_sier_available()))
                return 0;
 
+       if (idx == PERF_REG_POWERPC_MMCRA &&
+          (IS_ENABLED(CONFIG_FSL_EMB_PERF_EVENT) ||
+           IS_ENABLED(CONFIG_PPC32)))
+               return 0;
+
        return regs_get_register(regs, pt_regs_offset[idx]);
 }
 
index a1aaa15..f0e488d 100644 (file)
@@ -237,12 +237,12 @@ static int ocm_debugfs_show(struct seq_file *m, void *v)
                        continue;
 
                seq_printf(m, "PPC4XX OCM   : %d\n", ocm->index);
-               seq_printf(m, "PhysAddr     : %pa[p]\n", &(ocm->phys));
+               seq_printf(m, "PhysAddr     : %pa\n", &(ocm->phys));
                seq_printf(m, "MemTotal     : %d Bytes\n", ocm->memtotal);
                seq_printf(m, "MemTotal(NC) : %d Bytes\n", ocm->nc.memtotal);
                seq_printf(m, "MemTotal(C)  : %d Bytes\n\n", ocm->c.memtotal);
 
-               seq_printf(m, "NC.PhysAddr  : %pa[p]\n", &(ocm->nc.phys));
+               seq_printf(m, "NC.PhysAddr  : %pa\n", &(ocm->nc.phys));
                seq_printf(m, "NC.VirtAddr  : 0x%p\n", ocm->nc.virt);
                seq_printf(m, "NC.MemTotal  : %d Bytes\n", ocm->nc.memtotal);
                seq_printf(m, "NC.MemFree   : %d Bytes\n", ocm->nc.memfree);
@@ -252,7 +252,7 @@ static int ocm_debugfs_show(struct seq_file *m, void *v)
                                                        blk->size, blk->owner);
                }
 
-               seq_printf(m, "\nC.PhysAddr   : %pa[p]\n", &(ocm->c.phys));
+               seq_printf(m, "\nC.PhysAddr   : %pa\n", &(ocm->c.phys));
                seq_printf(m, "C.VirtAddr   : 0x%p\n", ocm->c.virt);
                seq_printf(m, "C.MemTotal   : %d Bytes\n", ocm->c.memtotal);
                seq_printf(m, "C.MemFree    : %d Bytes\n", ocm->c.memfree);
index e66644e..9438fa0 100644 (file)
@@ -538,8 +538,7 @@ static void __init chrp_init_IRQ(void)
        /* see if there is a keyboard in the device tree
           with a parent of type "adb" */
        for_each_node_by_name(kbd, "keyboard")
-               if (kbd->parent && kbd->parent->type
-                   && strcmp(kbd->parent->type, "adb") == 0)
+               if (of_node_is_type(kbd->parent, "adb"))
                        break;
        of_node_put(kbd);
        if (kbd)
index d18d164..bdf9b71 100644 (file)
@@ -255,7 +255,7 @@ int pasemi_dma_alloc_ring(struct pasemi_dmachan *chan, int ring_size)
 
        chan->ring_size = ring_size;
 
-       chan->ring_virt = dma_zalloc_coherent(&dma_pdev->dev,
+       chan->ring_virt = dma_alloc_coherent(&dma_pdev->dev,
                                             ring_size * sizeof(u64),
                                             &chan->ring_dma, GFP_KERNEL);
 
index d7f742e..3f58c7d 100644 (file)
@@ -564,7 +564,7 @@ struct iommu_table_group *pnv_try_setup_npu_table_group(struct pnv_ioda_pe *pe)
                }
        } else {
                /* Create a group for 1 GPU and attached NPUs for POWER8 */
-               pe->npucomp = kzalloc(sizeof(pe->npucomp), GFP_KERNEL);
+               pe->npucomp = kzalloc(sizeof(*pe->npucomp), GFP_KERNEL);
                table_group = &pe->npucomp->table_group;
                table_group->ops = &pnv_npu_peers_ops;
                iommu_register_group(table_group, hose->global_number,
index 1d6406a..145373f 100644 (file)
@@ -1593,6 +1593,8 @@ static void pnv_ioda_setup_vf_PE(struct pci_dev *pdev, u16 num_vfs)
 
                pnv_pci_ioda2_setup_dma_pe(phb, pe);
 #ifdef CONFIG_IOMMU_API
+               iommu_register_group(&pe->table_group,
+                               pe->phb->hose->global_number, pe->pe_number);
                pnv_ioda_setup_bus_iommu_group(pe, &pe->table_group, NULL);
 #endif
        }
@@ -2681,7 +2683,8 @@ static void pnv_pci_ioda_setup_iommu_api(void)
        list_for_each_entry(hose, &hose_list, list_node) {
                phb = hose->private_data;
 
-               if (phb->type == PNV_PHB_NPU_NVLINK)
+               if (phb->type == PNV_PHB_NPU_NVLINK ||
+                   phb->type == PNV_PHB_NPU_OCAPI)
                        continue;
 
                list_for_each_entry(pe, &phb->ioda.pe_list, list) {
index 45fb70b..ef9448a 100644 (file)
@@ -1147,6 +1147,8 @@ static int pnv_tce_iommu_bus_notifier(struct notifier_block *nb,
                        return 0;
 
                pe = &phb->ioda.pe_array[pdn->pe_number];
+               if (!pe->table_group.group)
+                       return 0;
                iommu_add_device(&pe->table_group, dev);
                return 0;
        case BUS_NOTIFY_DEL_DEVICE:
index 7d6457a..bba281b 100644 (file)
@@ -43,6 +43,7 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
 {
        unsigned long ret[PLPAR_HCALL_BUFSIZE];
        uint64_t rc, token;
+       uint64_t saved = 0;
 
        /*
         * When the hypervisor cannot map all the requested memory in a single
@@ -56,6 +57,8 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
                rc = plpar_hcall(H_SCM_BIND_MEM, ret, p->drc_index, 0,
                                p->blocks, BIND_ANY_ADDR, token);
                token = ret[0];
+               if (!saved)
+                       saved = ret[1];
                cond_resched();
        } while (rc == H_BUSY);
 
@@ -64,7 +67,7 @@ static int drc_pmem_bind(struct papr_scm_priv *p)
                return -ENXIO;
        }
 
-       p->bound_addr = ret[1];
+       p->bound_addr = saved;
 
        dev_dbg(&p->pdev->dev, "bound drc %x to %pR\n", p->drc_index, &p->res);
 
index 7725825..37a77e5 100644 (file)
@@ -264,7 +264,9 @@ void __init pSeries_final_fixup(void)
                        if (!of_device_is_compatible(nvdn->parent,
                                                "ibm,power9-npu"))
                                continue;
+#ifdef CONFIG_PPC_POWERNV
                        WARN_ON_ONCE(pnv_npu2_init(hose));
+#endif
                        break;
                }
        }
index 8b0ebf3..ebed46f 100644 (file)
@@ -756,9 +756,10 @@ fsl_open_outb_mbox(struct rio_mport *mport, void *dev_id, int mbox, int entries)
        }
 
        /* Initialize outbound message descriptor ring */
-       rmu->msg_tx_ring.virt = dma_zalloc_coherent(priv->dev,
-                               rmu->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
-                               &rmu->msg_tx_ring.phys, GFP_KERNEL);
+       rmu->msg_tx_ring.virt = dma_alloc_coherent(priv->dev,
+                                                  rmu->msg_tx_ring.size * RIO_MSG_DESC_SIZE,
+                                                  &rmu->msg_tx_ring.phys,
+                                                  GFP_KERNEL);
        if (!rmu->msg_tx_ring.virt) {
                rc = -ENOMEM;
                goto out_dma;
index e0d7d61..515fc3c 100644 (file)
@@ -28,11 +28,13 @@ config RISCV
        select GENERIC_STRNLEN_USER
        select GENERIC_SMP_IDLE_THREAD
        select GENERIC_ATOMIC64 if !64BIT || !RISCV_ISA_A
+       select HAVE_ARCH_AUDITSYSCALL
        select HAVE_MEMBLOCK_NODE_MAP
        select HAVE_DMA_CONTIGUOUS
        select HAVE_FUTEX_CMPXCHG if FUTEX
        select HAVE_GENERIC_DMA_COHERENT
        select HAVE_PERF_EVENTS
+       select HAVE_SYSCALL_TRACEPOINTS
        select IRQ_DOMAIN
        select RISCV_ISA_A if SMP
        select SPARSE_IRQ
@@ -40,6 +42,7 @@ config RISCV
        select HAVE_ARCH_TRACEHOOK
        select HAVE_PCI
        select MODULES_USE_ELF_RELA if MODULES
+       select MODULE_SECTIONS if MODULES
        select THREAD_INFO_IN_TASK
        select PCI_DOMAINS_GENERIC if PCI
        select PCI_MSI if PCI
@@ -100,7 +103,7 @@ choice
        prompt "Base ISA"
        default ARCH_RV64I
        help
-         This selects the base ISA that this kernel will traget and must match
+         This selects the base ISA that this kernel will target and must match
          the target platform.
 
 config ARCH_RV32I
@@ -152,7 +155,6 @@ choice
                bool "2GiB"
        config MAXPHYSMEM_128GB
                depends on 64BIT && CMODEL_MEDANY
-               select MODULE_SECTIONS if MODULES
                bool "128GiB"
 endchoice
 
index f399659..2fd3461 100644 (file)
@@ -13,8 +13,6 @@ CONFIG_BLK_DEV_INITRD=y
 CONFIG_EXPERT=y
 CONFIG_BPF_SYSCALL=y
 CONFIG_SMP=y
-CONFIG_PCI=y
-CONFIG_PCIE_XILINX=y
 CONFIG_MODULES=y
 CONFIG_MODULE_UNLOAD=y
 CONFIG_NET=y
@@ -28,6 +26,10 @@ CONFIG_IP_PNP_DHCP=y
 CONFIG_IP_PNP_BOOTP=y
 CONFIG_IP_PNP_RARP=y
 CONFIG_NETLINK_DIAG=y
+CONFIG_PCI=y
+CONFIG_PCIEPORTBUS=y
+CONFIG_PCI_HOST_GENERIC=y
+CONFIG_PCIE_XILINX=y
 CONFIG_DEVTMPFS=y
 CONFIG_BLK_DEV_LOOP=y
 CONFIG_VIRTIO_BLK=y
@@ -63,7 +65,6 @@ CONFIG_USB_STORAGE=y
 CONFIG_USB_UAS=y
 CONFIG_VIRTIO_MMIO=y
 CONFIG_SIFIVE_PLIC=y
-CONFIG_RAS=y
 CONFIG_EXT4_FS=y
 CONFIG_EXT4_FS_POSIX_ACL=y
 CONFIG_AUTOFS4_FS=y
@@ -77,5 +78,6 @@ CONFIG_NFS_V4_1=y
 CONFIG_NFS_V4_2=y
 CONFIG_ROOT_NFS=y
 CONFIG_CRYPTO_USER_API_HASH=y
+CONFIG_CRYPTO_DEV_VIRTIO=y
 CONFIG_PRINTK_TIME=y
 # CONFIG_RCU_TRACE is not set
index cd2af4b..46202da 100644 (file)
@@ -9,12 +9,12 @@
 #define MODULE_ARCH_VERMAGIC    "riscv"
 
 struct module;
-u64 module_emit_got_entry(struct module *mod, u64 val);
-u64 module_emit_plt_entry(struct module *mod, u64 val);
+unsigned long module_emit_got_entry(struct module *mod, unsigned long val);
+unsigned long module_emit_plt_entry(struct module *mod, unsigned long val);
 
 #ifdef CONFIG_MODULE_SECTIONS
 struct mod_section {
-       struct elf64_shdr *shdr;
+       Elf_Shdr *shdr;
        int num_entries;
        int max_entries;
 };
@@ -26,18 +26,18 @@ struct mod_arch_specific {
 };
 
 struct got_entry {
-       u64 symbol_addr;        /* the real variable address */
+       unsigned long symbol_addr;      /* the real variable address */
 };
 
-static inline struct got_entry emit_got_entry(u64 val)
+static inline struct got_entry emit_got_entry(unsigned long val)
 {
        return (struct got_entry) {val};
 }
 
-static inline struct got_entry *get_got_entry(u64 val,
+static inline struct got_entry *get_got_entry(unsigned long val,
                                              const struct mod_section *sec)
 {
-       struct got_entry *got = (struct got_entry *)sec->shdr->sh_addr;
+       struct got_entry *got = (struct got_entry *)(sec->shdr->sh_addr);
        int i;
        for (i = 0; i < sec->num_entries; i++) {
                if (got[i].symbol_addr == val)
@@ -62,7 +62,9 @@ struct plt_entry {
 #define REG_T0     0x5
 #define REG_T1     0x6
 
-static inline struct plt_entry emit_plt_entry(u64 val, u64 plt, u64 got_plt)
+static inline struct plt_entry emit_plt_entry(unsigned long val,
+                                             unsigned long plt,
+                                             unsigned long got_plt)
 {
        /*
         * U-Type encoding:
@@ -76,7 +78,7 @@ static inline struct plt_entry emit_plt_entry(u64 val, u64 plt, u64 got_plt)
         * +------------+------------+--------+----------+----------+
         *
         */
-       u64 offset = got_plt - plt;
+       unsigned long offset = got_plt - plt;
        u32 hi20 = (offset + 0x800) & 0xfffff000;
        u32 lo12 = (offset - hi20);
        return (struct plt_entry) {
@@ -86,7 +88,7 @@ static inline struct plt_entry emit_plt_entry(u64 val, u64 plt, u64 got_plt)
        };
 }
 
-static inline int get_got_plt_idx(u64 val, const struct mod_section *sec)
+static inline int get_got_plt_idx(unsigned long val, const struct mod_section *sec)
 {
        struct got_entry *got_plt = (struct got_entry *)sec->shdr->sh_addr;
        int i;
@@ -97,9 +99,9 @@ static inline int get_got_plt_idx(u64 val, const struct mod_section *sec)
        return -1;
 }
 
-static inline struct plt_entry *get_plt_entry(u64 val,
-                                     const struct mod_section *sec_plt,
-                                     const struct mod_section *sec_got_plt)
+static inline struct plt_entry *get_plt_entry(unsigned long val,
+                                             const struct mod_section *sec_plt,
+                                             const struct mod_section *sec_got_plt)
 {
        struct plt_entry *plt = (struct plt_entry *)sec_plt->shdr->sh_addr;
        int got_plt_idx = get_got_plt_idx(val, sec_got_plt);
index 06cfbb3..2a546a5 100644 (file)
@@ -80,7 +80,7 @@ typedef struct page *pgtable_t;
 #define __pgd(x)       ((pgd_t) { (x) })
 #define __pgprot(x)    ((pgprot_t) { (x) })
 
-#ifdef CONFIG_64BITS
+#ifdef CONFIG_64BIT
 #define PTE_FMT "%016lx"
 #else
 #define PTE_FMT "%08lx"
index 2fa2942..470755c 100644 (file)
 #define _PAGE_SPECIAL   _PAGE_SOFT
 #define _PAGE_TABLE     _PAGE_PRESENT
 
+/*
+ * _PAGE_PROT_NONE is set on not-present pages (and ignored by the hardware) to
+ * distinguish them from swapped out pages
+ */
+#define _PAGE_PROT_NONE _PAGE_READ
+
 #define _PAGE_PFN_SHIFT 10
 
 /* Set of bits to preserve across pte_modify() */
index 1630196..a8179a8 100644 (file)
@@ -44,7 +44,7 @@
 /* Page protection bits */
 #define _PAGE_BASE     (_PAGE_PRESENT | _PAGE_ACCESSED | _PAGE_USER)
 
-#define PAGE_NONE              __pgprot(0)
+#define PAGE_NONE              __pgprot(_PAGE_PROT_NONE)
 #define PAGE_READ              __pgprot(_PAGE_BASE | _PAGE_READ)
 #define PAGE_WRITE             __pgprot(_PAGE_BASE | _PAGE_READ | _PAGE_WRITE)
 #define PAGE_EXEC              __pgprot(_PAGE_BASE | _PAGE_EXEC)
@@ -98,7 +98,7 @@ extern unsigned long empty_zero_page[PAGE_SIZE / sizeof(unsigned long)];
 
 static inline int pmd_present(pmd_t pmd)
 {
-       return (pmd_val(pmd) & _PAGE_PRESENT);
+       return (pmd_val(pmd) & (_PAGE_PRESENT | _PAGE_PROT_NONE));
 }
 
 static inline int pmd_none(pmd_t pmd)
@@ -178,7 +178,7 @@ static inline pte_t *pte_offset_kernel(pmd_t *pmd, unsigned long addr)
 
 static inline int pte_present(pte_t pte)
 {
-       return (pte_val(pte) & _PAGE_PRESENT);
+       return (pte_val(pte) & (_PAGE_PRESENT | _PAGE_PROT_NONE));
 }
 
 static inline int pte_none(pte_t pte)
@@ -380,7 +380,7 @@ static inline int ptep_clear_flush_young(struct vm_area_struct *vma,
  *
  * Format of swap PTE:
  *     bit            0:       _PAGE_PRESENT (zero)
- *     bit            1:       reserved for future use (zero)
+ *     bit            1:       _PAGE_PROT_NONE (zero)
  *     bits      2 to 6:       swap type
  *     bits 7 to XLEN-1:       swap offset
  */
index 0531f49..ce70bce 100644 (file)
@@ -22,7 +22,7 @@
  * This decides where the kernel will search for a free chunk of vm
  * space during mmap's.
  */
-#define TASK_UNMAPPED_BASE     PAGE_ALIGN(TASK_SIZE >> 1)
+#define TASK_UNMAPPED_BASE     PAGE_ALIGN(TASK_SIZE / 3)
 
 #define STACK_TOP              TASK_SIZE
 #define STACK_TOP_MAX          STACK_TOP
index bbe1862..d35ec2f 100644 (file)
@@ -113,6 +113,11 @@ static inline void frame_pointer_set(struct pt_regs *regs,
        SET_FP(regs, val);
 }
 
+static inline unsigned long regs_return_value(struct pt_regs *regs)
+{
+       return regs->a0;
+}
+
 #endif /* __ASSEMBLY__ */
 
 #endif /* _ASM_RISCV_PTRACE_H */
index 8d25f89..bba3da6 100644 (file)
@@ -18,6 +18,7 @@
 #ifndef _ASM_RISCV_SYSCALL_H
 #define _ASM_RISCV_SYSCALL_H
 
+#include <uapi/linux/audit.h>
 #include <linux/sched.h>
 #include <linux/err.h>
 
@@ -99,4 +100,13 @@ static inline void syscall_set_arguments(struct task_struct *task,
        memcpy(&regs->a1 + i * sizeof(regs->a1), args, n * sizeof(regs->a0));
 }
 
+static inline int syscall_get_arch(void)
+{
+#ifdef CONFIG_64BIT
+       return AUDIT_ARCH_RISCV64;
+#else
+       return AUDIT_ARCH_RISCV32;
+#endif
+}
+
 #endif /* _ASM_RISCV_SYSCALL_H */
index f8fa1cd..1c9cc83 100644 (file)
@@ -80,13 +80,19 @@ struct thread_info {
 #define TIF_RESTORE_SIGMASK    4       /* restore signal mask in do_signal() */
 #define TIF_MEMDIE             5       /* is terminating due to OOM killer */
 #define TIF_SYSCALL_TRACEPOINT  6       /* syscall tracepoint instrumentation */
+#define TIF_SYSCALL_AUDIT      7       /* syscall auditing */
 
 #define _TIF_SYSCALL_TRACE     (1 << TIF_SYSCALL_TRACE)
 #define _TIF_NOTIFY_RESUME     (1 << TIF_NOTIFY_RESUME)
 #define _TIF_SIGPENDING                (1 << TIF_SIGPENDING)
 #define _TIF_NEED_RESCHED      (1 << TIF_NEED_RESCHED)
+#define _TIF_SYSCALL_TRACEPOINT        (1 << TIF_SYSCALL_TRACEPOINT)
+#define _TIF_SYSCALL_AUDIT     (1 << TIF_SYSCALL_AUDIT)
 
 #define _TIF_WORK_MASK \
        (_TIF_NOTIFY_RESUME | _TIF_SIGPENDING | _TIF_NEED_RESCHED)
 
+#define _TIF_SYSCALL_WORK \
+       (_TIF_SYSCALL_TRACE | _TIF_SYSCALL_TRACEPOINT | _TIF_SYSCALL_AUDIT)
+
 #endif /* _ASM_RISCV_THREAD_INFO_H */
index fef96f1..073ee80 100644 (file)
@@ -19,3 +19,5 @@
 #define __ARCH_WANT_SYS_CLONE
 
 #include <uapi/asm/unistd.h>
+
+#define NR_syscalls (__NR_syscalls)
index 6a92a2f..dac9834 100644 (file)
@@ -39,6 +39,7 @@ void asm_offsets(void)
        OFFSET(TASK_STACK, task_struct, stack);
        OFFSET(TASK_TI, task_struct, thread_info);
        OFFSET(TASK_TI_FLAGS, task_struct, thread_info.flags);
+       OFFSET(TASK_TI_PREEMPT_COUNT, task_struct, thread_info.preempt_count);
        OFFSET(TASK_TI_KERNEL_SP, task_struct, thread_info.kernel_sp);
        OFFSET(TASK_TI_USER_SP, task_struct, thread_info.user_sp);
        OFFSET(TASK_TI_CPU, task_struct, thread_info.cpu);
index 13d4826..fd9b57c 100644 (file)
@@ -144,6 +144,10 @@ _save_context:
        REG_L x2,  PT_SP(sp)
        .endm
 
+#if !IS_ENABLED(CONFIG_PREEMPT)
+.set resume_kernel, restore_all
+#endif
+
 ENTRY(handle_exception)
        SAVE_ALL
 
@@ -201,7 +205,7 @@ handle_syscall:
        REG_S s2, PT_SEPC(sp)
        /* Trace syscalls, but only if requested by the user. */
        REG_L t0, TASK_TI_FLAGS(tp)
-       andi t0, t0, _TIF_SYSCALL_TRACE
+       andi t0, t0, _TIF_SYSCALL_WORK
        bnez t0, handle_syscall_trace_enter
 check_syscall_nr:
        /* Check to make sure we don't jump to a bogus syscall number. */
@@ -221,14 +225,14 @@ ret_from_syscall:
        REG_S a0, PT_A0(sp)
        /* Trace syscalls, but only if requested by the user. */
        REG_L t0, TASK_TI_FLAGS(tp)
-       andi t0, t0, _TIF_SYSCALL_TRACE
+       andi t0, t0, _TIF_SYSCALL_WORK
        bnez t0, handle_syscall_trace_exit
 
 ret_from_exception:
        REG_L s0, PT_SSTATUS(sp)
        csrc sstatus, SR_SIE
        andi s0, s0, SR_SPP
-       bnez s0, restore_all
+       bnez s0, resume_kernel
 
 resume_userspace:
        /* Interrupts must be disabled here so flags are checked atomically */
@@ -250,6 +254,18 @@ restore_all:
        RESTORE_ALL
        sret
 
+#if IS_ENABLED(CONFIG_PREEMPT)
+resume_kernel:
+       REG_L s0, TASK_TI_PREEMPT_COUNT(tp)
+       bnez s0, restore_all
+need_resched:
+       REG_L s0, TASK_TI_FLAGS(tp)
+       andi s0, s0, _TIF_NEED_RESCHED
+       beqz s0, restore_all
+       call preempt_schedule_irq
+       j need_resched
+#endif
+
 work_pending:
        /* Enter slow path for supplementary processing */
        la ra, ret_from_exception
index bbbd26e..c9ae483 100644 (file)
@@ -9,14 +9,14 @@
 #include <linux/kernel.h>
 #include <linux/module.h>
 
-u64 module_emit_got_entry(struct module *mod, u64 val)
+unsigned long module_emit_got_entry(struct module *mod, unsigned long val)
 {
        struct mod_section *got_sec = &mod->arch.got;
        int i = got_sec->num_entries;
        struct got_entry *got = get_got_entry(val, got_sec);
 
        if (got)
-               return (u64)got;
+               return (unsigned long)got;
 
        /* There is no duplicate entry, create a new one */
        got = (struct got_entry *)got_sec->shdr->sh_addr;
@@ -25,10 +25,10 @@ u64 module_emit_got_entry(struct module *mod, u64 val)
        got_sec->num_entries++;
        BUG_ON(got_sec->num_entries > got_sec->max_entries);
 
-       return (u64)&got[i];
+       return (unsigned long)&got[i];
 }
 
-u64 module_emit_plt_entry(struct module *mod, u64 val)
+unsigned long module_emit_plt_entry(struct module *mod, unsigned long val)
 {
        struct mod_section *got_plt_sec = &mod->arch.got_plt;
        struct got_entry *got_plt;
@@ -37,27 +37,29 @@ u64 module_emit_plt_entry(struct module *mod, u64 val)
        int i = plt_sec->num_entries;
 
        if (plt)
-               return (u64)plt;
+               return (unsigned long)plt;
 
        /* There is no duplicate entry, create a new one */
        got_plt = (struct got_entry *)got_plt_sec->shdr->sh_addr;
        got_plt[i] = emit_got_entry(val);
        plt = (struct plt_entry *)plt_sec->shdr->sh_addr;
-       plt[i] = emit_plt_entry(val, (u64)&plt[i], (u64)&got_plt[i]);
+       plt[i] = emit_plt_entry(val,
+                               (unsigned long)&plt[i],
+                               (unsigned long)&got_plt[i]);
 
        plt_sec->num_entries++;
        got_plt_sec->num_entries++;
        BUG_ON(plt_sec->num_entries > plt_sec->max_entries);
 
-       return (u64)&plt[i];
+       return (unsigned long)&plt[i];
 }
 
-static int is_rela_equal(const Elf64_Rela *x, const Elf64_Rela *y)
+static int is_rela_equal(const Elf_Rela *x, const Elf_Rela *y)
 {
        return x->r_info == y->r_info && x->r_addend == y->r_addend;
 }
 
-static bool duplicate_rela(const Elf64_Rela *rela, int idx)
+static bool duplicate_rela(const Elf_Rela *rela, int idx)
 {
        int i;
        for (i = 0; i < idx; i++) {
@@ -67,13 +69,13 @@ static bool duplicate_rela(const Elf64_Rela *rela, int idx)
        return false;
 }
 
-static void count_max_entries(Elf64_Rela *relas, int num,
+static void count_max_entries(Elf_Rela *relas, int num,
                              unsigned int *plts, unsigned int *gots)
 {
        unsigned int type, i;
 
        for (i = 0; i < num; i++) {
-               type = ELF64_R_TYPE(relas[i].r_info);
+               type = ELF_RISCV_R_TYPE(relas[i].r_info);
                if (type == R_RISCV_CALL_PLT) {
                        if (!duplicate_rela(relas, i))
                                (*plts)++;
@@ -118,9 +120,9 @@ int module_frob_arch_sections(Elf_Ehdr *ehdr, Elf_Shdr *sechdrs,
 
        /* Calculate the maxinum number of entries */
        for (i = 0; i < ehdr->e_shnum; i++) {
-               Elf64_Rela *relas = (void *)ehdr + sechdrs[i].sh_offset;
-               int num_rela = sechdrs[i].sh_size / sizeof(Elf64_Rela);
-               Elf64_Shdr *dst_sec = sechdrs + sechdrs[i].sh_info;
+               Elf_Rela *relas = (void *)ehdr + sechdrs[i].sh_offset;
+               int num_rela = sechdrs[i].sh_size / sizeof(Elf_Rela);
+               Elf_Shdr *dst_sec = sechdrs + sechdrs[i].sh_info;
 
                if (sechdrs[i].sh_type != SHT_RELA)
                        continue;
index 60f1e02..2ae5e02 100644 (file)
 #include <asm/ptrace.h>
 #include <asm/syscall.h>
 #include <asm/thread_info.h>
+#include <linux/audit.h>
 #include <linux/ptrace.h>
 #include <linux/elf.h>
 #include <linux/regset.h>
 #include <linux/sched.h>
 #include <linux/sched/task_stack.h>
 #include <linux/tracehook.h>
+
+#define CREATE_TRACE_POINTS
 #include <trace/events/syscalls.h>
 
 enum riscv_regset {
@@ -163,15 +166,19 @@ void do_syscall_trace_enter(struct pt_regs *regs)
        if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
                trace_sys_enter(regs, syscall_get_nr(current, regs));
 #endif
+
+       audit_syscall_entry(regs->a7, regs->a0, regs->a1, regs->a2, regs->a3);
 }
 
 void do_syscall_trace_exit(struct pt_regs *regs)
 {
+       audit_syscall_exit(regs);
+
        if (test_thread_flag(TIF_SYSCALL_TRACE))
                tracehook_report_syscall_exit(regs, 0);
 
 #ifdef CONFIG_HAVE_SYSCALL_TRACEPOINTS
        if (test_thread_flag(TIF_SYSCALL_TRACEPOINT))
-               trace_sys_exit(regs, regs->regs[0]);
+               trace_sys_exit(regs, regs_return_value(regs));
 #endif
 }
index fc8006a..7756431 100644 (file)
@@ -149,7 +149,14 @@ asmlinkage void __init setup_vm(void)
 
 void __init parse_dtb(unsigned int hartid, void *dtb)
 {
-       early_init_dt_scan(__va(dtb));
+       if (!early_init_dt_scan(__va(dtb)))
+               return;
+
+       pr_err("No DTB passed to the kernel\n");
+#ifdef CONFIG_CMDLINE_FORCE
+       strlcpy(boot_command_line, CONFIG_CMDLINE, COMMAND_LINE_SIZE);
+       pr_info("Forcing kernel command line to: %s\n", boot_command_line);
+#endif
 }
 
 static void __init setup_bootmem(void)
@@ -174,7 +181,7 @@ static void __init setup_bootmem(void)
        BUG_ON(mem_size == 0);
 
        set_max_mapnr(PFN_DOWN(mem_size));
-       max_low_pfn = memblock_end_of_DRAM();
+       max_low_pfn = PFN_DOWN(memblock_end_of_DRAM());
 
 #ifdef CONFIG_BLK_DEV_INITRD
        setup_initrd();
index 57b1383..246635e 100644 (file)
@@ -23,6 +23,7 @@
 #include <linux/smp.h>
 #include <linux/sched.h>
 #include <linux/seq_file.h>
+#include <linux/delay.h>
 
 #include <asm/sbi.h>
 #include <asm/tlbflush.h>
@@ -31,6 +32,7 @@
 enum ipi_message_type {
        IPI_RESCHEDULE,
        IPI_CALL_FUNC,
+       IPI_CPU_STOP,
        IPI_MAX
 };
 
@@ -66,6 +68,13 @@ int setup_profiling_timer(unsigned int multiplier)
        return -EINVAL;
 }
 
+static void ipi_stop(void)
+{
+       set_cpu_online(smp_processor_id(), false);
+       while (1)
+               wait_for_interrupt();
+}
+
 void riscv_software_interrupt(void)
 {
        unsigned long *pending_ipis = &ipi_data[smp_processor_id()].bits;
@@ -94,6 +103,11 @@ void riscv_software_interrupt(void)
                        generic_smp_call_function_interrupt();
                }
 
+               if (ops & (1 << IPI_CPU_STOP)) {
+                       stats[IPI_CPU_STOP]++;
+                       ipi_stop();
+               }
+
                BUG_ON((ops >> IPI_MAX) != 0);
 
                /* Order data access and bit testing. */
@@ -121,6 +135,7 @@ send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation)
 static const char * const ipi_names[] = {
        [IPI_RESCHEDULE]        = "Rescheduling interrupts",
        [IPI_CALL_FUNC]         = "Function call interrupts",
+       [IPI_CPU_STOP]          = "CPU stop interrupts",
 };
 
 void show_ipi_stats(struct seq_file *p, int prec)
@@ -146,15 +161,29 @@ void arch_send_call_function_single_ipi(int cpu)
        send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC);
 }
 
-static void ipi_stop(void *unused)
-{
-       while (1)
-               wait_for_interrupt();
-}
-
 void smp_send_stop(void)
 {
-       on_each_cpu(ipi_stop, NULL, 1);
+       unsigned long timeout;
+
+       if (num_online_cpus() > 1) {
+               cpumask_t mask;
+
+               cpumask_copy(&mask, cpu_online_mask);
+               cpumask_clear_cpu(smp_processor_id(), &mask);
+
+               if (system_state <= SYSTEM_RUNNING)
+                       pr_crit("SMP: stopping secondary CPUs\n");
+               send_ipi_message(&mask, IPI_CPU_STOP);
+       }
+
+       /* Wait up to one second for other CPUs to stop */
+       timeout = USEC_PER_SEC;
+       while (num_online_cpus() > 1 && timeout--)
+               udelay(1);
+
+       if (num_online_cpus() > 1)
+               pr_warn("SMP: failed to stop secondary CPUs %*pbl\n",
+                          cpumask_pr_args(cpu_online_mask));
 }
 
 void smp_send_reschedule(int cpu)
index fc185ec..18cda0e 100644 (file)
@@ -57,15 +57,12 @@ void __init setup_smp(void)
 
        while ((dn = of_find_node_by_type(dn, "cpu"))) {
                hart = riscv_of_processor_hartid(dn);
-               if (hart < 0) {
-                       of_node_put(dn);
+               if (hart < 0)
                        continue;
-               }
 
                if (hart == cpuid_to_hartid_map(0)) {
                        BUG_ON(found_boot_cpu);
                        found_boot_cpu = 1;
-                       of_node_put(dn);
                        continue;
                }
 
@@ -73,7 +70,6 @@ void __init setup_smp(void)
                set_cpu_possible(cpuid, true);
                set_cpu_present(cpuid, true);
                cpuid++;
-               of_node_put(dn);
        }
 
        BUG_ON(!found_boot_cpu);
index 1d9bfaf..658ebf6 100644 (file)
@@ -28,7 +28,8 @@ static void __init zone_sizes_init(void)
        unsigned long max_zone_pfns[MAX_NR_ZONES] = { 0, };
 
 #ifdef CONFIG_ZONE_DMA32
-       max_zone_pfns[ZONE_DMA32] = PFN_DOWN(min(4UL * SZ_1G, max_low_pfn));
+       max_zone_pfns[ZONE_DMA32] = PFN_DOWN(min(4UL * SZ_1G,
+                       (unsigned long) PFN_PHYS(max_low_pfn)));
 #endif
        max_zone_pfns[ZONE_NORMAL] = max_low_pfn;
 
index ccbb53e..8d04e6f 100644 (file)
@@ -25,7 +25,7 @@ static inline int init_new_context(struct task_struct *tsk,
        atomic_set(&mm->context.flush_count, 0);
        mm->context.gmap_asce = 0;
        mm->context.flush_mm = 0;
-       mm->context.compat_mm = 0;
+       mm->context.compat_mm = test_thread_flag(TIF_31BIT);
 #ifdef CONFIG_PGSTE
        mm->context.alloc_pgste = page_table_allocate_pgste ||
                test_thread_flag(TIF_PGSTE) ||
@@ -90,8 +90,6 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
 {
        int cpu = smp_processor_id();
 
-       if (prev == next)
-               return;
        S390_lowcore.user_asce = next->context.asce;
        cpumask_set_cpu(cpu, &next->context.cpu_attach_mask);
        /* Clear previous user-ASCE from CR1 and CR7 */
@@ -103,7 +101,8 @@ static inline void switch_mm(struct mm_struct *prev, struct mm_struct *next,
                __ctl_load(S390_lowcore.vdso_asce, 7, 7);
                clear_cpu_flag(CIF_ASCE_SECONDARY);
        }
-       cpumask_clear_cpu(cpu, &prev->context.cpu_attach_mask);
+       if (prev != next)
+               cpumask_clear_cpu(cpu, &prev->context.cpu_attach_mask);
 }
 
 #define finish_arch_post_lock_switch finish_arch_post_lock_switch
index af5c2b3..a8c7789 100644 (file)
@@ -63,10 +63,10 @@ static noinline __init void detect_machine_type(void)
        if (stsi(vmms, 3, 2, 2) || !vmms->count)
                return;
 
-       /* Running under KVM? If not we assume z/VM */
+       /* Detect known hypervisors */
        if (!memcmp(vmms->vm[0].cpi, "\xd2\xe5\xd4", 3))
                S390_lowcore.machine_flags |= MACHINE_FLAG_KVM;
-       else
+       else if (!memcmp(vmms->vm[0].cpi, "\xa9\x61\xe5\xd4", 4))
                S390_lowcore.machine_flags |= MACHINE_FLAG_VM;
 }
 
index 72dd23e..7ed90a7 100644 (file)
@@ -1006,6 +1006,8 @@ void __init setup_arch(char **cmdline_p)
                pr_info("Linux is running under KVM in 64-bit mode\n");
        else if (MACHINE_IS_LPAR)
                pr_info("Linux is running natively in 64-bit mode\n");
+       else
+               pr_info("Linux is running as a guest in 64-bit mode\n");
 
        /* Have one command line that is parsed and saved in /proc/cmdline */
        /* boot_command_line has been already set up in early.c */
index f82b3d3..b198ece 100644 (file)
@@ -381,8 +381,13 @@ void smp_call_online_cpu(void (*func)(void *), void *data)
  */
 void smp_call_ipl_cpu(void (*func)(void *), void *data)
 {
+       struct lowcore *lc = pcpu_devices->lowcore;
+
+       if (pcpu_devices[0].address == stap())
+               lc = &S390_lowcore;
+
        pcpu_delegate(&pcpu_devices[0], func, data,
-                     pcpu_devices->lowcore->nodat_stack);
+                     lc->nodat_stack);
 }
 
 int smp_find_processor_id(u16 address)
@@ -1166,7 +1171,11 @@ static ssize_t __ref rescan_store(struct device *dev,
 {
        int rc;
 
+       rc = lock_device_hotplug_sysfs();
+       if (rc)
+               return rc;
        rc = smp_rescan_cpus();
+       unlock_device_hotplug();
        return rc ? rc : count;
 }
 static DEVICE_ATTR_WO(rescan);
index 537f97f..b6796e6 100644 (file)
        .section .text
 ENTRY(swsusp_arch_suspend)
        lg      %r1,__LC_NODAT_STACK
-       aghi    %r1,-STACK_FRAME_OVERHEAD
        stmg    %r6,%r15,__SF_GPRS(%r1)
+       aghi    %r1,-STACK_FRAME_OVERHEAD
        stg     %r15,__SF_BACKCHAIN(%r1)
-       lgr     %r1,%r15
+       lgr     %r15,%r1
 
        /* Store FPU registers */
        brasl   %r14,save_fpu_regs
index ebe748a..4ff3548 100644 (file)
@@ -224,10 +224,9 @@ int arch_setup_additional_pages(struct linux_binprm *bprm, int uses_interp)
 
        vdso_pages = vdso64_pages;
 #ifdef CONFIG_COMPAT
-       if (is_compat_task()) {
+       mm->context.compat_mm = is_compat_task();
+       if (mm->context.compat_mm)
                vdso_pages = vdso32_pages;
-               mm->context.compat_mm = 1;
-       }
 #endif
        /*
         * vDSO has a problem and was disabled, just don't "enable" it for
index a153257..d62fa14 100644 (file)
@@ -297,7 +297,7 @@ static int shadow_crycb(struct kvm_vcpu *vcpu, struct vsie_page *vsie_page)
        scb_s->crycbd = 0;
 
        apie_h = vcpu->arch.sie_block->eca & ECA_APIE;
-       if (!apie_h && !key_msk)
+       if (!apie_h && (!key_msk || fmt_o == CRYCB_FORMAT0))
                return 0;
 
        if (!crycb_addr)
index a966d7b..4266a4d 100644 (file)
@@ -382,7 +382,9 @@ static void zpci_irq_handler(struct airq_struct *airq)
                        if (ai == -1UL)
                                break;
                        inc_irq_stat(IRQIO_MSI);
+                       airq_iv_lock(aibv, ai);
                        generic_handle_irq(airq_iv_get_data(aibv, ai));
+                       airq_iv_unlock(aibv, ai);
                }
        }
 }
@@ -408,7 +410,7 @@ int arch_setup_msi_irqs(struct pci_dev *pdev, int nvec, int type)
        zdev->aisb = aisb;
 
        /* Create adapter interrupt vector */
-       zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA);
+       zdev->aibv = airq_iv_create(msi_vecs, AIRQ_IV_DATA | AIRQ_IV_BITLOCK);
        if (!zdev->aibv)
                return -ENOMEM;
 
index 01d0f7f..2563d1e 100644 (file)
@@ -1,3 +1,3 @@
 ifneq ($(CONFIG_BUILTIN_DTB_SOURCE),"")
-obj-y += $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_SOURCE)).dtb.o
+obj-$(CONFIG_USE_BUILTIN_DTB) += $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_SOURCE)).dtb.o
 endif
index 1372553..1d1544b 100644 (file)
@@ -28,6 +28,7 @@ generic-y += preempt.h
 generic-y += sections.h
 generic-y += segment.h
 generic-y += serial.h
+generic-y += shmparam.h
 generic-y += sizes.h
 generic-y += syscalls.h
 generic-y += topology.h
index 6185d4f..6826143 100644 (file)
@@ -198,7 +198,7 @@ config X86
        select IRQ_FORCED_THREADING
        select NEED_SG_DMA_LENGTH
        select PCI_DOMAINS                      if PCI
-       select PCI_LOCKLESS_CONFIG
+       select PCI_LOCKLESS_CONFIG              if PCI
        select PERF_EVENTS
        select RTC_LIB
        select RTC_MC146818_LIB
@@ -446,12 +446,12 @@ config RETPOLINE
          branches. Requires a compiler with -mindirect-branch=thunk-extern
          support for full protection. The kernel may run slower.
 
-config RESCTRL
-       bool "Resource Control support"
+config X86_CPU_RESCTRL
+       bool "x86 CPU resource control support"
        depends on X86 && (CPU_SUP_INTEL || CPU_SUP_AMD)
        select KERNFS
        help
-         Enable Resource Control support.
+         Enable x86 CPU resource control support.
 
          Provide support for the allocation and monitoring of system resources
          usage by the CPU.
@@ -617,7 +617,7 @@ config X86_INTEL_QUARK
 
 config X86_INTEL_LPSS
        bool "Intel Low Power Subsystem Support"
-       depends on X86 && ACPI
+       depends on X86 && ACPI && PCI
        select COMMON_CLK
        select PINCTRL
        select IOSF_MBI
index 6403789..f62e347 100644 (file)
@@ -600,6 +600,16 @@ ENTRY(trampoline_32bit_src)
        leal    TRAMPOLINE_32BIT_PGTABLE_OFFSET(%ecx), %eax
        movl    %eax, %cr3
 3:
+       /* Set EFER.LME=1 as a precaution in case hypervsior pulls the rug */
+       pushl   %ecx
+       pushl   %edx
+       movl    $MSR_EFER, %ecx
+       rdmsr
+       btsl    $_EFER_LME, %eax
+       wrmsr
+       popl    %edx
+       popl    %ecx
+
        /* Enable PAE and LA57 (if required) paging modes */
        movl    $X86_CR4_PAE, %eax
        cmpl    $0, %edx
index 91f7563..6ff7e81 100644 (file)
@@ -6,7 +6,7 @@
 #define TRAMPOLINE_32BIT_PGTABLE_OFFSET        0
 
 #define TRAMPOLINE_32BIT_CODE_OFFSET   PAGE_SIZE
-#define TRAMPOLINE_32BIT_CODE_SIZE     0x60
+#define TRAMPOLINE_32BIT_CODE_SIZE     0x70
 
 #define TRAMPOLINE_32BIT_STACK_END     TRAMPOLINE_32BIT_SIZE
 
index 8eaf895..3991377 100644 (file)
@@ -361,7 +361,8 @@ ENTRY(entry_INT80_compat)
 
        /* Need to switch before accessing the thread stack. */
        SWITCH_TO_KERNEL_CR3 scratch_reg=%rdi
-       movq    %rsp, %rdi
+       /* In the Xen PV case we already run on the thread stack. */
+       ALTERNATIVE "movq %rsp, %rdi", "jmp .Lint80_keep_stack", X86_FEATURE_XENPV
        movq    PER_CPU_VAR(cpu_current_top_of_stack), %rsp
 
        pushq   6*8(%rdi)               /* regs->ss */
@@ -370,8 +371,9 @@ ENTRY(entry_INT80_compat)
        pushq   3*8(%rdi)               /* regs->cs */
        pushq   2*8(%rdi)               /* regs->ip */
        pushq   1*8(%rdi)               /* regs->orig_ax */
-
        pushq   (%rdi)                  /* pt_regs->di */
+.Lint80_keep_stack:
+
        pushq   %rsi                    /* pt_regs->si */
        xorl    %esi, %esi              /* nospec   si */
        pushq   %rdx                    /* pt_regs->dx */
index 374a197..b684f02 100644 (file)
@@ -2278,6 +2278,19 @@ void perf_check_microcode(void)
                x86_pmu.check_microcode();
 }
 
+static int x86_pmu_check_period(struct perf_event *event, u64 value)
+{
+       if (x86_pmu.check_period && x86_pmu.check_period(event, value))
+               return -EINVAL;
+
+       if (value && x86_pmu.limit_period) {
+               if (x86_pmu.limit_period(event, value) > value)
+                       return -EINVAL;
+       }
+
+       return 0;
+}
+
 static struct pmu pmu = {
        .pmu_enable             = x86_pmu_enable,
        .pmu_disable            = x86_pmu_disable,
@@ -2302,6 +2315,7 @@ static struct pmu pmu = {
        .event_idx              = x86_pmu_event_idx,
        .sched_task             = x86_pmu_sched_task,
        .task_ctx_size          = sizeof(struct x86_perf_task_context),
+       .check_period           = x86_pmu_check_period,
 };
 
 void arch_perf_update_userpage(struct perf_event *event,
index 40e12cf..730978d 100644 (file)
@@ -3558,6 +3558,14 @@ static void free_excl_cntrs(int cpu)
 }
 
 static void intel_pmu_cpu_dying(int cpu)
+{
+       fini_debug_store_on_cpu(cpu);
+
+       if (x86_pmu.counter_freezing)
+               disable_counter_freeze();
+}
+
+static void intel_pmu_cpu_dead(int cpu)
 {
        struct cpu_hw_events *cpuc = &per_cpu(cpu_hw_events, cpu);
        struct intel_shared_regs *pc;
@@ -3570,11 +3578,6 @@ static void intel_pmu_cpu_dying(int cpu)
        }
 
        free_excl_cntrs(cpu);
-
-       fini_debug_store_on_cpu(cpu);
-
-       if (x86_pmu.counter_freezing)
-               disable_counter_freeze();
 }
 
 static void intel_pmu_sched_task(struct perf_event_context *ctx,
@@ -3584,6 +3587,11 @@ static void intel_pmu_sched_task(struct perf_event_context *ctx,
        intel_pmu_lbr_sched_task(ctx, sched_in);
 }
 
+static int intel_pmu_check_period(struct perf_event *event, u64 value)
+{
+       return intel_pmu_has_bts_period(event, value) ? -EINVAL : 0;
+}
+
 PMU_FORMAT_ATTR(offcore_rsp, "config1:0-63");
 
 PMU_FORMAT_ATTR(ldlat, "config1:0-15");
@@ -3663,6 +3671,9 @@ static __initconst const struct x86_pmu core_pmu = {
        .cpu_prepare            = intel_pmu_cpu_prepare,
        .cpu_starting           = intel_pmu_cpu_starting,
        .cpu_dying              = intel_pmu_cpu_dying,
+       .cpu_dead               = intel_pmu_cpu_dead,
+
+       .check_period           = intel_pmu_check_period,
 };
 
 static struct attribute *intel_pmu_attrs[];
@@ -3703,8 +3714,12 @@ static __initconst const struct x86_pmu intel_pmu = {
        .cpu_prepare            = intel_pmu_cpu_prepare,
        .cpu_starting           = intel_pmu_cpu_starting,
        .cpu_dying              = intel_pmu_cpu_dying,
+       .cpu_dead               = intel_pmu_cpu_dead,
+
        .guest_get_msrs         = intel_guest_get_msrs,
        .sched_task             = intel_pmu_sched_task,
+
+       .check_period           = intel_pmu_check_period,
 };
 
 static __init void intel_clovertown_quirk(void)
index c07bee3..b10e043 100644 (file)
@@ -1222,6 +1222,8 @@ static struct pci_driver snbep_uncore_pci_driver = {
        .id_table       = snbep_uncore_pci_ids,
 };
 
+#define NODE_ID_MASK   0x7
+
 /*
  * build pci bus to socket mapping
  */
@@ -1243,7 +1245,7 @@ static int snbep_pci2phy_map_init(int devid, int nodeid_loc, int idmap_loc, bool
                err = pci_read_config_dword(ubox_dev, nodeid_loc, &config);
                if (err)
                        break;
-               nodeid = config;
+               nodeid = config & NODE_ID_MASK;
                /* get the Node ID mapping */
                err = pci_read_config_dword(ubox_dev, idmap_loc, &config);
                if (err)
index 78d7b70..d46fd67 100644 (file)
@@ -646,6 +646,11 @@ struct x86_pmu {
         * Intel host/guest support (KVM)
         */
        struct perf_guest_switch_msr *(*guest_get_msrs)(int *nr);
+
+       /*
+        * Check period value for PERF_EVENT_IOC_PERIOD ioctl.
+        */
+       int (*check_period) (struct perf_event *event, u64 period);
 };
 
 struct x86_perf_task_context {
@@ -857,7 +862,7 @@ static inline int amd_pmu_init(void)
 
 #ifdef CONFIG_CPU_SUP_INTEL
 
-static inline bool intel_pmu_has_bts(struct perf_event *event)
+static inline bool intel_pmu_has_bts_period(struct perf_event *event, u64 period)
 {
        struct hw_perf_event *hwc = &event->hw;
        unsigned int hw_event, bts_event;
@@ -868,7 +873,14 @@ static inline bool intel_pmu_has_bts(struct perf_event *event)
        hw_event = hwc->config & INTEL_ARCH_EVENT_MASK;
        bts_event = x86_pmu.event_map(PERF_COUNT_HW_BRANCH_INSTRUCTIONS);
 
-       return hw_event == bts_event && hwc->sample_period == 1;
+       return hw_event == bts_event && period == 1;
+}
+
+static inline bool intel_pmu_has_bts(struct perf_event *event)
+{
+       struct hw_perf_event *hwc = &event->hw;
+
+       return intel_pmu_has_bts_period(event, hwc->sample_period);
 }
 
 int intel_pmu_save_and_restart(struct perf_event *event);
index f65b78d..7dbbe9f 100644 (file)
@@ -51,7 +51,7 @@ static unsigned long get_dr(int n)
 /*
  * fill in the user structure for a core dump..
  */
-static void dump_thread32(struct pt_regs *regs, struct user32 *dump)
+static void fill_dump(struct pt_regs *regs, struct user32 *dump)
 {
        u32 fs, gs;
        memset(dump, 0, sizeof(*dump));
@@ -157,10 +157,12 @@ static int aout_core_dump(struct coredump_params *cprm)
        fs = get_fs();
        set_fs(KERNEL_DS);
        has_dumped = 1;
+
+       fill_dump(cprm->regs, &dump);
+
        strncpy(dump.u_comm, current->comm, sizeof(current->comm));
        dump.u_ar0 = offsetof(struct user32, regs);
        dump.signal = cprm->siginfo->si_signo;
-       dump_thread32(cprm->regs, &dump);
 
        /*
         * If the size of the dump file exceeds the rlimit, then see
index 0dd6b0f..9f15384 100644 (file)
@@ -6,7 +6,7 @@
  * "Big Core" Processors (Branded as Core, Xeon, etc...)
  *
  * The "_X" parts are generally the EP and EX Xeons, or the
- * "Extreme" ones, like Broadwell-E.
+ * "Extreme" ones, like Broadwell-E, or Atom microserver.
  *
  * While adding a new CPUID for a new microarchitecture, add a new
  * group to keep logically sorted out in chronological order. Within
@@ -52,6 +52,8 @@
 
 #define INTEL_FAM6_CANNONLAKE_MOBILE   0x66
 
+#define INTEL_FAM6_ICELAKE_MOBILE      0x7E
+
 /* "Small Core" Processors (Atom) */
 
 #define INTEL_FAM6_ATOM_BONNELL                0x1C /* Diamondville, Pineview */
@@ -71,6 +73,7 @@
 #define INTEL_FAM6_ATOM_GOLDMONT       0x5C /* Apollo Lake */
 #define INTEL_FAM6_ATOM_GOLDMONT_X     0x5F /* Denverton */
 #define INTEL_FAM6_ATOM_GOLDMONT_PLUS  0x7A /* Gemini Lake */
+#define INTEL_FAM6_ATOM_TREMONT_X      0x86 /* Jacobsville */
 
 /* Xeon Phi */
 
index 4660ce9..1803733 100644 (file)
@@ -299,6 +299,7 @@ union kvm_mmu_extended_role {
                unsigned int cr4_smap:1;
                unsigned int cr4_smep:1;
                unsigned int cr4_la57:1;
+               unsigned int maxphyaddr:6;
        };
 };
 
@@ -397,6 +398,7 @@ struct kvm_mmu {
        void (*update_pte)(struct kvm_vcpu *vcpu, struct kvm_mmu_page *sp,
                           u64 *spte, const void *pte);
        hpa_t root_hpa;
+       gpa_t root_cr3;
        union kvm_mmu_role mmu_role;
        u8 root_level;
        u8 shadow_root_level;
index 0ca5061..19d18fa 100644 (file)
@@ -178,6 +178,10 @@ static inline void switch_ldt(struct mm_struct *prev, struct mm_struct *next)
 
 void enter_lazy_tlb(struct mm_struct *mm, struct task_struct *tsk);
 
+/*
+ * Init a new mm.  Used on mm copies, like at fork()
+ * and on mm's that are brand-new, like at execve().
+ */
 static inline int init_new_context(struct task_struct *tsk,
                                   struct mm_struct *mm)
 {
@@ -228,8 +232,22 @@ do {                                               \
 } while (0)
 #endif
 
+static inline void arch_dup_pkeys(struct mm_struct *oldmm,
+                                 struct mm_struct *mm)
+{
+#ifdef CONFIG_X86_INTEL_MEMORY_PROTECTION_KEYS
+       if (!cpu_feature_enabled(X86_FEATURE_OSPKE))
+               return;
+
+       /* Duplicate the oldmm pkey state in mm: */
+       mm->context.pkey_allocation_map = oldmm->context.pkey_allocation_map;
+       mm->context.execute_only_pkey   = oldmm->context.execute_only_pkey;
+#endif
+}
+
 static inline int arch_dup_mmap(struct mm_struct *oldmm, struct mm_struct *mm)
 {
+       arch_dup_pkeys(oldmm, mm);
        paravirt_arch_dup_mmap(oldmm, mm);
        return ldt_dup_context(oldmm, mm);
 }
index 8f65728..0ce558a 100644 (file)
@@ -7,7 +7,11 @@
 #endif
 
 #ifdef CONFIG_KASAN
+#ifdef CONFIG_KASAN_EXTRA
+#define KASAN_STACK_ORDER 2
+#else
 #define KASAN_STACK_ORDER 1
+#endif
 #else
 #define KASAN_STACK_ORDER 0
 #endif
index 40616e8..2779ace 100644 (file)
@@ -1065,7 +1065,7 @@ static inline void native_set_pte_at(struct mm_struct *mm, unsigned long addr,
 static inline void set_pmd_at(struct mm_struct *mm, unsigned long addr,
                              pmd_t *pmdp, pmd_t pmd)
 {
-       native_set_pmd(pmdp, pmd);
+       set_pmd(pmdp, pmd);
 }
 
 static inline void set_pud_at(struct mm_struct *mm, unsigned long addr,
index 54990fe..f6b7fe2 100644 (file)
@@ -2,7 +2,7 @@
 #ifndef _ASM_X86_RESCTRL_SCHED_H
 #define _ASM_X86_RESCTRL_SCHED_H
 
-#ifdef CONFIG_RESCTRL
+#ifdef CONFIG_X86_CPU_RESCTRL
 
 #include <linux/sched.h>
 #include <linux/jump_label.h>
@@ -88,6 +88,6 @@ static inline void resctrl_sched_in(void)
 
 static inline void resctrl_sched_in(void) {}
 
-#endif /* CONFIG_RESCTRL */
+#endif /* CONFIG_X86_CPU_RESCTRL */
 
 #endif /* _ASM_X86_RESCTRL_SCHED_H */
index a77445d..780f2b4 100644 (file)
@@ -711,7 +711,7 @@ static __must_check inline bool user_access_begin(const void __user *ptr, size_t
 {
        if (unlikely(!access_ok(ptr,len)))
                return 0;
-       __uaccess_begin();
+       __uaccess_begin_nospec();
        return 1;
 }
 #define user_access_begin(a,b) user_access_begin(a,b)
index e652a7c..3f697a9 100644 (file)
@@ -48,7 +48,8 @@ enum {
        BIOS_STATUS_SUCCESS             =  0,
        BIOS_STATUS_UNIMPLEMENTED       = -ENOSYS,
        BIOS_STATUS_EINVAL              = -EINVAL,
-       BIOS_STATUS_UNAVAIL             = -EBUSY
+       BIOS_STATUS_UNAVAIL             = -EBUSY,
+       BIOS_STATUS_ABORT               = -EINTR,
 };
 
 /* Address map parameters */
@@ -167,4 +168,9 @@ extern long system_serial_number;
 
 extern struct kobject *sgi_uv_kobj;    /* /sys/firmware/sgi_uv */
 
+/*
+ * EFI runtime lock; cf. firmware/efi/runtime-wrappers.c for details
+ */
+extern struct semaphore __efi_uv_runtime_lock;
+
 #endif /* _ASM_X86_UV_BIOS_H */
index ac78f90..cfd24f9 100644 (file)
@@ -39,7 +39,7 @@ obj-$(CONFIG_CPU_SUP_UMC_32)          += umc.o
 obj-$(CONFIG_X86_MCE)                  += mce/
 obj-$(CONFIG_MTRR)                     += mtrr/
 obj-$(CONFIG_MICROCODE)                        += microcode/
-obj-$(CONFIG_RESCTRL)                  += resctrl/
+obj-$(CONFIG_X86_CPU_RESCTRL)          += resctrl/
 
 obj-$(CONFIG_X86_LOCAL_APIC)           += perfctr-watchdog.o
 
index 8654b8b..01874d5 100644 (file)
@@ -71,7 +71,7 @@ void __init check_bugs(void)
         * identify_boot_cpu() initialized SMT support information, let the
         * core code know.
         */
-       cpu_smt_check_topology_early();
+       cpu_smt_check_topology();
 
        if (!IS_ENABLED(CONFIG_SMP)) {
                pr_info("CPU: ");
@@ -215,7 +215,7 @@ static enum spectre_v2_mitigation spectre_v2_enabled __ro_after_init =
 static enum spectre_v2_user_mitigation spectre_v2_user __ro_after_init =
        SPECTRE_V2_USER_NONE;
 
-#ifdef RETPOLINE
+#ifdef CONFIG_RETPOLINE
 static bool spectre_v2_bad_module;
 
 bool retpoline_module_ok(bool has_retpoline)
index 672c722..6ce290c 100644 (file)
@@ -784,6 +784,7 @@ static int mce_no_way_out(struct mce *m, char **msg, unsigned long *validp,
                        quirk_no_way_out(i, m, regs);
 
                if (mce_severity(m, mca_cfg.tolerant, &tmp, true) >= MCE_PANIC_SEVERITY) {
+                       m->bank = i;
                        mce_read_aux(m, i);
                        *msg = tmp;
                        return 1;
index 51adde0..e1f3ba1 100644 (file)
@@ -855,7 +855,7 @@ load_microcode_amd(bool save, u8 family, const u8 *data, size_t size)
        if (!p) {
                return ret;
        } else {
-               if (boot_cpu_data.microcode == p->patch_id)
+               if (boot_cpu_data.microcode >= p->patch_id)
                        return ret;
 
                ret = UCODE_NEW;
index 6895049..4a06c37 100644 (file)
@@ -1,4 +1,4 @@
 # SPDX-License-Identifier: GPL-2.0
-obj-$(CONFIG_RESCTRL)  += core.o rdtgroup.o monitor.o
-obj-$(CONFIG_RESCTRL)  += ctrlmondata.o pseudo_lock.o
+obj-$(CONFIG_X86_CPU_RESCTRL)  += core.o rdtgroup.o monitor.o
+obj-$(CONFIG_X86_CPU_RESCTRL)  += ctrlmondata.o pseudo_lock.o
 CFLAGS_pseudo_lock.o = -I$(src)
index c8b07d8..17ffc86 100644 (file)
@@ -470,6 +470,7 @@ int crash_load_segments(struct kimage *image)
 
        kbuf.memsz = kbuf.bufsz;
        kbuf.buf_align = ELF_CORE_HEADER_ALIGN;
+       kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
        ret = kexec_add_buffer(&kbuf);
        if (ret) {
                vfree((void *)image->arch.elf_headers);
index b0acb22..dfd3aca 100644 (file)
 
 #define HPET_MASK                      CLOCKSOURCE_MASK(32)
 
-/* FSEC = 10^-15
-   NSEC = 10^-9 */
-#define FSEC_PER_NSEC                  1000000L
-
 #define HPET_DEV_USED_BIT              2
 #define HPET_DEV_USED                  (1 << HPET_DEV_USED_BIT)
 #define HPET_DEV_VALID                 0x8
index 278cd07..53917a3 100644 (file)
@@ -167,6 +167,9 @@ setup_efi_state(struct boot_params *params, unsigned long params_load_addr,
        struct efi_info *current_ei = &boot_params.efi_info;
        struct efi_info *ei = &params->efi_info;
 
+       if (!efi_enabled(EFI_RUNTIME_SERVICES))
+               return 0;
+
        if (!current_ei->efi_memmap_size)
                return 0;
 
@@ -434,6 +437,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
        kbuf.memsz = PAGE_ALIGN(header->init_size);
        kbuf.buf_align = header->kernel_alignment;
        kbuf.buf_min = MIN_KERNEL_LOAD_ADDR;
+       kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
        ret = kexec_add_buffer(&kbuf);
        if (ret)
                goto out_free_params;
@@ -448,6 +452,7 @@ static void *bzImage64_load(struct kimage *image, char *kernel,
                kbuf.bufsz = kbuf.memsz = initrd_len;
                kbuf.buf_align = PAGE_SIZE;
                kbuf.buf_min = MIN_INITRD_LOAD_ADDR;
+               kbuf.mem = KEXEC_BUF_MEM_UNKNOWN;
                ret = kexec_add_buffer(&kbuf);
                if (ret)
                        goto out_free_params;
index ba4bfb7..5c93a65 100644 (file)
@@ -457,6 +457,7 @@ static void __send_ipi_mask(const struct cpumask *mask, int vector)
 #else
        u64 ipi_bitmap = 0;
 #endif
+       long ret;
 
        if (cpumask_empty(mask))
                return;
@@ -482,8 +483,9 @@ static void __send_ipi_mask(const struct cpumask *mask, int vector)
                } else if (apic_id < min + KVM_IPI_CLUSTER_SIZE) {
                        max = apic_id < max ? max : apic_id;
                } else {
-                       kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap,
+                       ret = kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap,
                                (unsigned long)(ipi_bitmap >> BITS_PER_LONG), min, icr);
+                       WARN_ONCE(ret < 0, "KVM: failed to send PV IPI: %ld", ret);
                        min = max = apic_id;
                        ipi_bitmap = 0;
                }
@@ -491,8 +493,9 @@ static void __send_ipi_mask(const struct cpumask *mask, int vector)
        }
 
        if (ipi_bitmap) {
-               kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap,
+               ret = kvm_hypercall4(KVM_HC_SEND_IPI, (unsigned long)ipi_bitmap,
                        (unsigned long)(ipi_bitmap >> BITS_PER_LONG), min, icr);
+               WARN_ONCE(ret < 0, "KVM: failed to send PV IPI: %ld", ret);
        }
 
        local_irq_restore(flags);
index e9f777b..3fae238 100644 (file)
@@ -297,15 +297,16 @@ static int __init tsc_setup(char *str)
 
 __setup("tsc=", tsc_setup);
 
-#define MAX_RETRIES     5
-#define SMI_TRESHOLD    50000
+#define MAX_RETRIES            5
+#define TSC_DEFAULT_THRESHOLD  0x20000
 
 /*
- * Read TSC and the reference counters. Take care of SMI disturbance
+ * Read TSC and the reference counters. Take care of any disturbances
  */
 static u64 tsc_read_refs(u64 *p, int hpet)
 {
        u64 t1, t2;
+       u64 thresh = tsc_khz ? tsc_khz >> 5 : TSC_DEFAULT_THRESHOLD;
        int i;
 
        for (i = 0; i < MAX_RETRIES; i++) {
@@ -315,7 +316,7 @@ static u64 tsc_read_refs(u64 *p, int hpet)
                else
                        *p = acpi_pm_read_early();
                t2 = get_cycles();
-               if ((t2 - t1) < SMI_TRESHOLD)
+               if ((t2 - t1) < thresh)
                        return t2;
        }
        return ULLONG_MAX;
@@ -703,15 +704,15 @@ static unsigned long pit_hpet_ptimer_calibrate_cpu(void)
         * zero. In each wait loop iteration we read the TSC and check
         * the delta to the previous read. We keep track of the min
         * and max values of that delta. The delta is mostly defined
-        * by the IO time of the PIT access, so we can detect when a
-        * SMI/SMM disturbance happened between the two reads. If the
+        * by the IO time of the PIT access, so we can detect when
+        * any disturbance happened between the two reads. If the
         * maximum time is significantly larger than the minimum time,
         * then we discard the result and have another try.
         *
         * 2) Reference counter. If available we use the HPET or the
         * PMTIMER as a reference to check the sanity of that value.
         * We use separate TSC readouts and check inside of the
-        * reference read for a SMI/SMM disturbance. We dicard
+        * reference read for any possible disturbance. We dicard
         * disturbed values here as well. We do that around the PIT
         * calibration delay loop as we have to wait for a certain
         * amount of time anyway.
@@ -744,7 +745,7 @@ static unsigned long pit_hpet_ptimer_calibrate_cpu(void)
                if (ref1 == ref2)
                        continue;
 
-               /* Check, whether the sampling was disturbed by an SMI */
+               /* Check, whether the sampling was disturbed */
                if (tsc1 == ULLONG_MAX || tsc2 == ULLONG_MAX)
                        continue;
 
@@ -1268,7 +1269,7 @@ static DECLARE_DELAYED_WORK(tsc_irqwork, tsc_refine_calibration_work);
  */
 static void tsc_refine_calibration_work(struct work_struct *work)
 {
-       static u64 tsc_start = -1, ref_start;
+       static u64 tsc_start = ULLONG_MAX, ref_start;
        static int hpet;
        u64 tsc_stop, ref_stop, delta;
        unsigned long freq;
@@ -1283,14 +1284,15 @@ static void tsc_refine_calibration_work(struct work_struct *work)
         * delayed the first time we expire. So set the workqueue
         * again once we know timers are working.
         */
-       if (tsc_start == -1) {
+       if (tsc_start == ULLONG_MAX) {
+restart:
                /*
                 * Only set hpet once, to avoid mixing hardware
                 * if the hpet becomes enabled later.
                 */
                hpet = is_hpet_enabled();
-               schedule_delayed_work(&tsc_irqwork, HZ);
                tsc_start = tsc_read_refs(&ref_start, hpet);
+               schedule_delayed_work(&tsc_irqwork, HZ);
                return;
        }
 
@@ -1300,9 +1302,9 @@ static void tsc_refine_calibration_work(struct work_struct *work)
        if (ref_start == ref_stop)
                goto out;
 
-       /* Check, whether the sampling was disturbed by an SMI */
-       if (tsc_start == ULLONG_MAX || tsc_stop == ULLONG_MAX)
-               goto out;
+       /* Check, whether the sampling was disturbed */
+       if (tsc_stop == ULLONG_MAX)
+               goto restart;
 
        delta = tsc_stop - tsc_start;
        delta *= 1000000LL;
index 69b3a7c..31ecf7a 100644 (file)
@@ -2,10 +2,6 @@
 
 ccflags-y += -Iarch/x86/kvm
 
-CFLAGS_x86.o := -I.
-CFLAGS_svm.o := -I.
-CFLAGS_vmx.o := -I.
-
 KVM := ../../../virt/kvm
 
 kvm-y                  += $(KVM)/kvm_main.o $(KVM)/coalesced_mmio.o \
index bbffa6c..c07958b 100644 (file)
@@ -335,6 +335,7 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
        unsigned f_xsaves = kvm_x86_ops->xsaves_supported() ? F(XSAVES) : 0;
        unsigned f_umip = kvm_x86_ops->umip_emulated() ? F(UMIP) : 0;
        unsigned f_intel_pt = kvm_x86_ops->pt_supported() ? F(INTEL_PT) : 0;
+       unsigned f_la57 = 0;
 
        /* cpuid 1.edx */
        const u32 kvm_cpuid_1_edx_x86_features =
@@ -489,7 +490,10 @@ static inline int __do_cpuid_ent(struct kvm_cpuid_entry2 *entry, u32 function,
                        // TSC_ADJUST is emulated
                        entry->ebx |= F(TSC_ADJUST);
                        entry->ecx &= kvm_cpuid_7_0_ecx_x86_features;
+                       f_la57 = entry->ecx & F(LA57);
                        cpuid_mask(&entry->ecx, CPUID_7_ECX);
+                       /* Set LA57 based on hardware capability. */
+                       entry->ecx |= f_la57;
                        entry->ecx |= f_umip;
                        /* PKU is not yet implemented for shadow paging. */
                        if (!tdp_enabled || !boot_cpu_has(X86_FEATURE_OSPKE))
index c90a535..89d20ed 100644 (file)
@@ -1636,7 +1636,7 @@ int kvm_hv_hypercall(struct kvm_vcpu *vcpu)
                ret = kvm_hvcall_signal_event(vcpu, fast, ingpa);
                if (ret != HV_STATUS_INVALID_PORT_ID)
                        break;
-               /* maybe userspace knows this conn_id: fall through */
+               /* fall through - maybe userspace knows this conn_id. */
        case HVCALL_POST_MESSAGE:
                /* don't bother userspace if it has no way to handle it */
                if (unlikely(rep || !vcpu_to_synic(vcpu)->active)) {
@@ -1832,7 +1832,6 @@ int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
                        ent->eax |= HV_X64_MSR_VP_INDEX_AVAILABLE;
                        ent->eax |= HV_X64_MSR_RESET_AVAILABLE;
                        ent->eax |= HV_MSR_REFERENCE_TSC_AVAILABLE;
-                       ent->eax |= HV_X64_MSR_GUEST_IDLE_AVAILABLE;
                        ent->eax |= HV_X64_ACCESS_FREQUENCY_MSRS;
                        ent->eax |= HV_X64_ACCESS_REENLIGHTENMENT;
 
@@ -1848,11 +1847,11 @@ int kvm_vcpu_ioctl_get_hv_cpuid(struct kvm_vcpu *vcpu, struct kvm_cpuid2 *cpuid,
                case HYPERV_CPUID_ENLIGHTMENT_INFO:
                        ent->eax |= HV_X64_REMOTE_TLB_FLUSH_RECOMMENDED;
                        ent->eax |= HV_X64_APIC_ACCESS_RECOMMENDED;
-                       ent->eax |= HV_X64_SYSTEM_RESET_RECOMMENDED;
                        ent->eax |= HV_X64_RELAXED_TIMING_RECOMMENDED;
                        ent->eax |= HV_X64_CLUSTER_IPI_RECOMMENDED;
                        ent->eax |= HV_X64_EX_PROCESSOR_MASKS_RECOMMENDED;
-                       ent->eax |= HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
+                       if (evmcs_ver)
+                               ent->eax |= HV_X64_ENLIGHTENED_VMCS_RECOMMENDED;
 
                        /*
                         * Default number of spinlock retry attempts, matches
index 9f089e2..4b6c2da 100644 (file)
@@ -1035,6 +1035,7 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
        switch (delivery_mode) {
        case APIC_DM_LOWEST:
                vcpu->arch.apic_arb_prio++;
+               /* fall through */
        case APIC_DM_FIXED:
                if (unlikely(trig_mode && !level))
                        break;
@@ -1874,6 +1875,7 @@ int kvm_lapic_reg_write(struct kvm_lapic *apic, u32 reg, u32 val)
 
        case APIC_LVT0:
                apic_manage_nmi_watchdog(apic, val);
+               /* fall through */
        case APIC_LVTTHMR:
        case APIC_LVTPC:
        case APIC_LVT1:
index ce770b4..f2d1d23 100644 (file)
@@ -3555,6 +3555,7 @@ void kvm_mmu_free_roots(struct kvm_vcpu *vcpu, struct kvm_mmu *mmu,
                                                           &invalid_list);
                        mmu->root_hpa = INVALID_PAGE;
                }
+               mmu->root_cr3 = 0;
        }
 
        kvm_mmu_commit_zap_page(vcpu->kvm, &invalid_list);
@@ -3610,6 +3611,7 @@ static int mmu_alloc_direct_roots(struct kvm_vcpu *vcpu)
                vcpu->arch.mmu->root_hpa = __pa(vcpu->arch.mmu->pae_root);
        } else
                BUG();
+       vcpu->arch.mmu->root_cr3 = vcpu->arch.mmu->get_cr3(vcpu);
 
        return 0;
 }
@@ -3618,10 +3620,11 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
 {
        struct kvm_mmu_page *sp;
        u64 pdptr, pm_mask;
-       gfn_t root_gfn;
+       gfn_t root_gfn, root_cr3;
        int i;
 
-       root_gfn = vcpu->arch.mmu->get_cr3(vcpu) >> PAGE_SHIFT;
+       root_cr3 = vcpu->arch.mmu->get_cr3(vcpu);
+       root_gfn = root_cr3 >> PAGE_SHIFT;
 
        if (mmu_check_root(vcpu, root_gfn))
                return 1;
@@ -3646,7 +3649,7 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
                ++sp->root_count;
                spin_unlock(&vcpu->kvm->mmu_lock);
                vcpu->arch.mmu->root_hpa = root;
-               return 0;
+               goto set_root_cr3;
        }
 
        /*
@@ -3712,6 +3715,9 @@ static int mmu_alloc_shadow_roots(struct kvm_vcpu *vcpu)
                vcpu->arch.mmu->root_hpa = __pa(vcpu->arch.mmu->lm_root);
        }
 
+set_root_cr3:
+       vcpu->arch.mmu->root_cr3 = root_cr3;
+
        return 0;
 }
 
@@ -4163,7 +4169,7 @@ static bool cached_root_available(struct kvm_vcpu *vcpu, gpa_t new_cr3,
        struct kvm_mmu_root_info root;
        struct kvm_mmu *mmu = vcpu->arch.mmu;
 
-       root.cr3 = mmu->get_cr3(vcpu);
+       root.cr3 = mmu->root_cr3;
        root.hpa = mmu->root_hpa;
 
        for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++) {
@@ -4176,6 +4182,7 @@ static bool cached_root_available(struct kvm_vcpu *vcpu, gpa_t new_cr3,
        }
 
        mmu->root_hpa = root.hpa;
+       mmu->root_cr3 = root.cr3;
 
        return i < KVM_MMU_NUM_PREV_ROOTS;
 }
@@ -4371,6 +4378,7 @@ __reset_rsvds_bits_mask(struct kvm_vcpu *vcpu,
                        rsvd_bits(maxphyaddr, 51);
                rsvd_check->rsvd_bits_mask[1][4] =
                        rsvd_check->rsvd_bits_mask[0][4];
+               /* fall through */
        case PT64_ROOT_4LEVEL:
                rsvd_check->rsvd_bits_mask[0][3] = exb_bit_rsvd |
                        nonleaf_bit8_rsvd | rsvd_bits(7, 7) |
@@ -4769,6 +4777,7 @@ static union kvm_mmu_extended_role kvm_calc_mmu_role_ext(struct kvm_vcpu *vcpu)
        ext.cr4_pse = !!is_pse(vcpu);
        ext.cr4_pke = !!kvm_read_cr4_bits(vcpu, X86_CR4_PKE);
        ext.cr4_la57 = !!kvm_read_cr4_bits(vcpu, X86_CR4_LA57);
+       ext.maxphyaddr = cpuid_maxphyaddr(vcpu);
 
        ext.valid = 1;
 
@@ -5515,11 +5524,13 @@ int kvm_mmu_create(struct kvm_vcpu *vcpu)
        vcpu->arch.walk_mmu = &vcpu->arch.root_mmu;
 
        vcpu->arch.root_mmu.root_hpa = INVALID_PAGE;
+       vcpu->arch.root_mmu.root_cr3 = 0;
        vcpu->arch.root_mmu.translate_gpa = translate_gpa;
        for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++)
                vcpu->arch.root_mmu.prev_roots[i] = KVM_MMU_ROOT_INFO_INVALID;
 
        vcpu->arch.guest_mmu.root_hpa = INVALID_PAGE;
+       vcpu->arch.guest_mmu.root_cr3 = 0;
        vcpu->arch.guest_mmu.translate_gpa = translate_gpa;
        for (i = 0; i < KVM_MMU_NUM_PREV_ROOTS; i++)
                vcpu->arch.guest_mmu.prev_roots[i] = KVM_MMU_ROOT_INFO_INVALID;
index 307e5bd..f13a3a2 100644 (file)
@@ -3414,6 +3414,14 @@ static int nested_svm_vmexit(struct vcpu_svm *svm)
        kvm_mmu_reset_context(&svm->vcpu);
        kvm_mmu_load(&svm->vcpu);
 
+       /*
+        * Drop what we picked up for L2 via svm_complete_interrupts() so it
+        * doesn't end up in L1.
+        */
+       svm->vcpu.arch.nmi_injected = false;
+       kvm_clear_exception_queue(&svm->vcpu);
+       kvm_clear_interrupt_queue(&svm->vcpu);
+
        return 0;
 }
 
@@ -4395,7 +4403,7 @@ static int svm_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr)
        case MSR_IA32_APICBASE:
                if (kvm_vcpu_apicv_active(vcpu))
                        avic_update_vapic_bar(to_svm(vcpu), data);
-               /* Follow through */
+               /* Fall through */
        default:
                return kvm_set_msr_common(vcpu, msr);
        }
@@ -4504,28 +4512,19 @@ static int avic_incomplete_ipi_interception(struct vcpu_svm *svm)
                kvm_lapic_reg_write(apic, APIC_ICR, icrl);
                break;
        case AVIC_IPI_FAILURE_TARGET_NOT_RUNNING: {
-               int i;
-               struct kvm_vcpu *vcpu;
-               struct kvm *kvm = svm->vcpu.kvm;
                struct kvm_lapic *apic = svm->vcpu.arch.apic;
 
                /*
-                * At this point, we expect that the AVIC HW has already
-                * set the appropriate IRR bits on the valid target
-                * vcpus. So, we just need to kick the appropriate vcpu.
+                * Update ICR high and low, then emulate sending IPI,
+                * which is handled when writing APIC_ICR.
                 */
-               kvm_for_each_vcpu(i, vcpu, kvm) {
-                       bool m = kvm_apic_match_dest(vcpu, apic,
-                                                    icrl & KVM_APIC_SHORT_MASK,
-                                                    GET_APIC_DEST_FIELD(icrh),
-                                                    icrl & KVM_APIC_DEST_MASK);
-
-                       if (m && !avic_vcpu_is_running(vcpu))
-                               kvm_vcpu_wake_up(vcpu);
-               }
+               kvm_lapic_reg_write(apic, APIC_ICR2, icrh);
+               kvm_lapic_reg_write(apic, APIC_ICR, icrl);
                break;
        }
        case AVIC_IPI_FAILURE_INVALID_TARGET:
+               WARN_ONCE(1, "Invalid IPI target: index=%u, vcpu=%d, icr=%#0x:%#0x\n",
+                         index, svm->vcpu.vcpu_id, icrh, icrl);
                break;
        case AVIC_IPI_FAILURE_INVALID_BACKING_PAGE:
                WARN_ONCE(1, "Invalid backing page\n");
@@ -6278,6 +6277,9 @@ static int sev_guest_init(struct kvm *kvm, struct kvm_sev_cmd *argp)
        int asid, ret;
 
        ret = -EBUSY;
+       if (unlikely(sev->active))
+               return ret;
+
        asid = sev_asid_new();
        if (asid < 0)
                return ret;
index 705f40a..6432d08 100644 (file)
@@ -1465,7 +1465,7 @@ TRACE_EVENT(kvm_hv_send_ipi_ex,
 #endif /* _TRACE_KVM_H */
 
 #undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH arch/x86/kvm
+#define TRACE_INCLUDE_PATH ../../arch/x86/kvm
 #undef TRACE_INCLUDE_FILE
 #define TRACE_INCLUDE_FILE trace
 
index 95bc224..5466c6d 100644 (file)
@@ -332,16 +332,17 @@ int nested_enable_evmcs(struct kvm_vcpu *vcpu,
                        uint16_t *vmcs_version)
 {
        struct vcpu_vmx *vmx = to_vmx(vcpu);
+       bool evmcs_already_enabled = vmx->nested.enlightened_vmcs_enabled;
+
+       vmx->nested.enlightened_vmcs_enabled = true;
 
        if (vmcs_version)
                *vmcs_version = nested_get_evmcs_version(vcpu);
 
        /* We don't support disabling the feature for simplicity. */
-       if (vmx->nested.enlightened_vmcs_enabled)
+       if (evmcs_already_enabled)
                return 0;
 
-       vmx->nested.enlightened_vmcs_enabled = true;
-
        vmx->nested.msrs.pinbased_ctls_high &= ~EVMCS1_UNSUPPORTED_PINCTRL;
        vmx->nested.msrs.entry_ctls_high &= ~EVMCS1_UNSUPPORTED_VMENTRY_CTRL;
        vmx->nested.msrs.exit_ctls_high &= ~EVMCS1_UNSUPPORTED_VMEXIT_CTRL;
index 3170e29..d737a51 100644 (file)
@@ -55,7 +55,7 @@ static u16 shadow_read_write_fields[] = {
 static int max_shadow_read_write_fields =
        ARRAY_SIZE(shadow_read_write_fields);
 
-void init_vmcs_shadow_fields(void)
+static void init_vmcs_shadow_fields(void)
 {
        int i, j;
 
@@ -211,6 +211,7 @@ static void free_nested(struct kvm_vcpu *vcpu)
        if (!vmx->nested.vmxon && !vmx->nested.smm.vmxon)
                return;
 
+       hrtimer_cancel(&vmx->nested.preemption_timer);
        vmx->nested.vmxon = false;
        vmx->nested.smm.vmxon = false;
        free_vpid(vmx->nested.vpid02);
@@ -2472,6 +2473,10 @@ static int nested_check_vm_execution_controls(struct kvm_vcpu *vcpu,
            (nested_cpu_has_vpid(vmcs12) && !vmcs12->virtual_processor_id))
                return -EINVAL;
 
+       if (!nested_cpu_has_preemption_timer(vmcs12) &&
+           nested_cpu_has_save_preemption_timer(vmcs12))
+               return -EINVAL;
+
        if (nested_cpu_has_ept(vmcs12) &&
            !valid_ept_address(vcpu, vmcs12->ept_pointer))
                return -EINVAL;
@@ -4140,11 +4145,11 @@ static int enter_vmx_operation(struct kvm_vcpu *vcpu)
        if (r < 0)
                goto out_vmcs02;
 
-       vmx->nested.cached_vmcs12 = kmalloc(VMCS12_SIZE, GFP_KERNEL);
+       vmx->nested.cached_vmcs12 = kzalloc(VMCS12_SIZE, GFP_KERNEL);
        if (!vmx->nested.cached_vmcs12)
                goto out_cached_vmcs12;
 
-       vmx->nested.cached_shadow_vmcs12 = kmalloc(VMCS12_SIZE, GFP_KERNEL);
+       vmx->nested.cached_shadow_vmcs12 = kzalloc(VMCS12_SIZE, GFP_KERNEL);
        if (!vmx->nested.cached_shadow_vmcs12)
                goto out_cached_shadow_vmcs12;
 
@@ -4540,9 +4545,8 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu)
                         * given physical address won't match the required
                         * VMCS12_REVISION identifier.
                         */
-                       nested_vmx_failValid(vcpu,
+                       return nested_vmx_failValid(vcpu,
                                VMXERR_VMPTRLD_INCORRECT_VMCS_REVISION_ID);
-                       return kvm_skip_emulated_instruction(vcpu);
                }
                new_vmcs12 = kmap(page);
                if (new_vmcs12->hdr.revision_id != VMCS12_REVISION ||
@@ -5264,13 +5268,17 @@ static int vmx_get_nested_state(struct kvm_vcpu *vcpu,
                        copy_shadow_to_vmcs12(vmx);
        }
 
-       if (copy_to_user(user_kvm_nested_state->data, vmcs12, sizeof(*vmcs12)))
+       /*
+        * Copy over the full allocated size of vmcs12 rather than just the size
+        * of the struct.
+        */
+       if (copy_to_user(user_kvm_nested_state->data, vmcs12, VMCS12_SIZE))
                return -EFAULT;
 
        if (nested_cpu_has_shadow_vmcs(vmcs12) &&
            vmcs12->vmcs_link_pointer != -1ull) {
                if (copy_to_user(user_kvm_nested_state->data + VMCS12_SIZE,
-                                get_shadow_vmcs12(vcpu), sizeof(*vmcs12)))
+                                get_shadow_vmcs12(vcpu), VMCS12_SIZE))
                        return -EFAULT;
        }
 
@@ -5553,9 +5561,11 @@ void nested_vmx_setup_ctls_msrs(struct nested_vmx_msrs *msrs, u32 ept_caps,
         * secondary cpu-based controls.  Do not include those that
         * depend on CPUID bits, they are added later by vmx_cpuid_update.
         */
-       rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2,
-               msrs->secondary_ctls_low,
-               msrs->secondary_ctls_high);
+       if (msrs->procbased_ctls_high & CPU_BASED_ACTIVATE_SECONDARY_CONTROLS)
+               rdmsr(MSR_IA32_VMX_PROCBASED_CTLS2,
+                     msrs->secondary_ctls_low,
+                     msrs->secondary_ctls_high);
+
        msrs->secondary_ctls_low = 0;
        msrs->secondary_ctls_high &=
                SECONDARY_EXEC_DESC |
index 4d39f73..30a6bcd 100644 (file)
@@ -26,6 +26,7 @@
 #include <linux/mod_devicetable.h>
 #include <linux/mm.h>
 #include <linux/sched.h>
+#include <linux/sched/smt.h>
 #include <linux/slab.h>
 #include <linux/tboot.h>
 #include <linux/trace_events.h>
@@ -423,7 +424,7 @@ static void check_ept_pointer_match(struct kvm *kvm)
        to_kvm_vmx(kvm)->ept_pointers_match = EPT_POINTERS_MATCH;
 }
 
-int kvm_fill_hv_flush_list_func(struct hv_guest_mapping_flush_list *flush,
+static int kvm_fill_hv_flush_list_func(struct hv_guest_mapping_flush_list *flush,
                void *data)
 {
        struct kvm_tlb_range *range = data;
@@ -453,7 +454,7 @@ static int hv_remote_flush_tlb_with_range(struct kvm *kvm,
                struct kvm_tlb_range *range)
 {
        struct kvm_vcpu *vcpu;
-       int ret = -ENOTSUPP, i;
+       int ret = 0, i;
 
        spin_lock(&to_kvm_vmx(kvm)->ept_pointer_lock);
 
@@ -862,7 +863,8 @@ static void add_atomic_switch_msr(struct vcpu_vmx *vmx, unsigned msr,
        if (!entry_only)
                j = find_msr(&m->host, msr);
 
-       if (i == NR_AUTOLOAD_MSRS || j == NR_AUTOLOAD_MSRS) {
+       if ((i < 0 && m->guest.nr == NR_AUTOLOAD_MSRS) ||
+               (j < 0 &&  m->host.nr == NR_AUTOLOAD_MSRS)) {
                printk_once(KERN_WARNING "Not enough msr switch entries. "
                                "Can't add msr %x\n", msr);
                return;
@@ -1192,21 +1194,6 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
        if (!pi_test_sn(pi_desc) && vcpu->cpu == cpu)
                return;
 
-       /*
-        * First handle the simple case where no cmpxchg is necessary; just
-        * allow posting non-urgent interrupts.
-        *
-        * If the 'nv' field is POSTED_INTR_WAKEUP_VECTOR, do not change
-        * PI.NDST: pi_post_block will do it for us and the wakeup_handler
-        * expects the VCPU to be on the blocked_vcpu_list that matches
-        * PI.NDST.
-        */
-       if (pi_desc->nv == POSTED_INTR_WAKEUP_VECTOR ||
-           vcpu->cpu == cpu) {
-               pi_clear_sn(pi_desc);
-               return;
-       }
-
        /* The full case.  */
        do {
                old.control = new.control = pi_desc->control;
@@ -1221,6 +1208,17 @@ static void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
                new.sn = 0;
        } while (cmpxchg64(&pi_desc->control, old.control,
                           new.control) != old.control);
+
+       /*
+        * Clear SN before reading the bitmap.  The VT-d firmware
+        * writes the bitmap and reads SN atomically (5.2.3 in the
+        * spec), so it doesn't really have a memory barrier that
+        * pairs with this, but we cannot do that and we need one.
+        */
+       smp_mb__after_atomic();
+
+       if (!bitmap_empty((unsigned long *)pi_desc->pir, NR_VECTORS))
+               pi_set_on(pi_desc);
 }
 
 /*
@@ -1773,7 +1771,7 @@ static int vmx_get_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                if (!msr_info->host_initiated &&
                    !guest_cpuid_has(vcpu, X86_FEATURE_RDTSCP))
                        return 1;
-               /* Otherwise falls through */
+               /* Else, falls through */
        default:
                msr = find_msr_entry(vmx, msr_info->index);
                if (msr) {
@@ -2014,7 +2012,7 @@ static int vmx_set_msr(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
                /* Check reserved bit, higher 32 bits should be zero */
                if ((data >> 32) != 0)
                        return 1;
-               /* Otherwise falls through */
+               /* Else, falls through */
        default:
                msr = find_msr_entry(vmx, msr_index);
                if (msr) {
@@ -2344,7 +2342,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf,
                case 37: /* AAT100 */
                case 44: /* BC86,AAY89,BD102 */
                case 46: /* BA97 */
-                       _vmexit_control &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
+                       _vmentry_control &= ~VM_ENTRY_LOAD_IA32_PERF_GLOBAL_CTRL;
                        _vmexit_control &= ~VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL;
                        pr_warn_once("kvm: VM_EXIT_LOAD_IA32_PERF_GLOBAL_CTRL "
                                        "does not work properly. Using workaround\n");
@@ -6362,72 +6360,9 @@ static void vmx_update_hv_timer(struct kvm_vcpu *vcpu)
        vmx->loaded_vmcs->hv_timer_armed = false;
 }
 
-static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
+static void __vmx_vcpu_run(struct kvm_vcpu *vcpu, struct vcpu_vmx *vmx)
 {
-       struct vcpu_vmx *vmx = to_vmx(vcpu);
-       unsigned long cr3, cr4, evmcs_rsp;
-
-       /* Record the guest's net vcpu time for enforced NMI injections. */
-       if (unlikely(!enable_vnmi &&
-                    vmx->loaded_vmcs->soft_vnmi_blocked))
-               vmx->loaded_vmcs->entry_time = ktime_get();
-
-       /* Don't enter VMX if guest state is invalid, let the exit handler
-          start emulation until we arrive back to a valid state */
-       if (vmx->emulation_required)
-               return;
-
-       if (vmx->ple_window_dirty) {
-               vmx->ple_window_dirty = false;
-               vmcs_write32(PLE_WINDOW, vmx->ple_window);
-       }
-
-       if (vmx->nested.need_vmcs12_sync)
-               nested_sync_from_vmcs12(vcpu);
-
-       if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty))
-               vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
-       if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty))
-               vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]);
-
-       cr3 = __get_current_cr3_fast();
-       if (unlikely(cr3 != vmx->loaded_vmcs->host_state.cr3)) {
-               vmcs_writel(HOST_CR3, cr3);
-               vmx->loaded_vmcs->host_state.cr3 = cr3;
-       }
-
-       cr4 = cr4_read_shadow();
-       if (unlikely(cr4 != vmx->loaded_vmcs->host_state.cr4)) {
-               vmcs_writel(HOST_CR4, cr4);
-               vmx->loaded_vmcs->host_state.cr4 = cr4;
-       }
-
-       /* When single-stepping over STI and MOV SS, we must clear the
-        * corresponding interruptibility bits in the guest state. Otherwise
-        * vmentry fails as it then expects bit 14 (BS) in pending debug
-        * exceptions being set, but that's not correct for the guest debugging
-        * case. */
-       if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
-               vmx_set_interrupt_shadow(vcpu, 0);
-
-       if (static_cpu_has(X86_FEATURE_PKU) &&
-           kvm_read_cr4_bits(vcpu, X86_CR4_PKE) &&
-           vcpu->arch.pkru != vmx->host_pkru)
-               __write_pkru(vcpu->arch.pkru);
-
-       pt_guest_enter(vmx);
-
-       atomic_switch_perf_msrs(vmx);
-
-       vmx_update_hv_timer(vcpu);
-
-       /*
-        * If this vCPU has touched SPEC_CTRL, restore the guest's value if
-        * it's non-zero. Since vmentry is serialising on affected CPUs, there
-        * is no need to worry about the conditional branch over the wrmsr
-        * being speculatively taken.
-        */
-       x86_spec_ctrl_set_guest(vmx->spec_ctrl, 0);
+       unsigned long evmcs_rsp;
 
        vmx->__launched = vmx->loaded_vmcs->launched;
 
@@ -6567,6 +6502,77 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
                , "eax", "ebx", "edi"
 #endif
              );
+}
+STACK_FRAME_NON_STANDARD(__vmx_vcpu_run);
+
+static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
+{
+       struct vcpu_vmx *vmx = to_vmx(vcpu);
+       unsigned long cr3, cr4;
+
+       /* Record the guest's net vcpu time for enforced NMI injections. */
+       if (unlikely(!enable_vnmi &&
+                    vmx->loaded_vmcs->soft_vnmi_blocked))
+               vmx->loaded_vmcs->entry_time = ktime_get();
+
+       /* Don't enter VMX if guest state is invalid, let the exit handler
+          start emulation until we arrive back to a valid state */
+       if (vmx->emulation_required)
+               return;
+
+       if (vmx->ple_window_dirty) {
+               vmx->ple_window_dirty = false;
+               vmcs_write32(PLE_WINDOW, vmx->ple_window);
+       }
+
+       if (vmx->nested.need_vmcs12_sync)
+               nested_sync_from_vmcs12(vcpu);
+
+       if (test_bit(VCPU_REGS_RSP, (unsigned long *)&vcpu->arch.regs_dirty))
+               vmcs_writel(GUEST_RSP, vcpu->arch.regs[VCPU_REGS_RSP]);
+       if (test_bit(VCPU_REGS_RIP, (unsigned long *)&vcpu->arch.regs_dirty))
+               vmcs_writel(GUEST_RIP, vcpu->arch.regs[VCPU_REGS_RIP]);
+
+       cr3 = __get_current_cr3_fast();
+       if (unlikely(cr3 != vmx->loaded_vmcs->host_state.cr3)) {
+               vmcs_writel(HOST_CR3, cr3);
+               vmx->loaded_vmcs->host_state.cr3 = cr3;
+       }
+
+       cr4 = cr4_read_shadow();
+       if (unlikely(cr4 != vmx->loaded_vmcs->host_state.cr4)) {
+               vmcs_writel(HOST_CR4, cr4);
+               vmx->loaded_vmcs->host_state.cr4 = cr4;
+       }
+
+       /* When single-stepping over STI and MOV SS, we must clear the
+        * corresponding interruptibility bits in the guest state. Otherwise
+        * vmentry fails as it then expects bit 14 (BS) in pending debug
+        * exceptions being set, but that's not correct for the guest debugging
+        * case. */
+       if (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)
+               vmx_set_interrupt_shadow(vcpu, 0);
+
+       if (static_cpu_has(X86_FEATURE_PKU) &&
+           kvm_read_cr4_bits(vcpu, X86_CR4_PKE) &&
+           vcpu->arch.pkru != vmx->host_pkru)
+               __write_pkru(vcpu->arch.pkru);
+
+       pt_guest_enter(vmx);
+
+       atomic_switch_perf_msrs(vmx);
+
+       vmx_update_hv_timer(vcpu);
+
+       /*
+        * If this vCPU has touched SPEC_CTRL, restore the guest's value if
+        * it's non-zero. Since vmentry is serialising on affected CPUs, there
+        * is no need to worry about the conditional branch over the wrmsr
+        * being speculatively taken.
+        */
+       x86_spec_ctrl_set_guest(vmx->spec_ctrl, 0);
+
+       __vmx_vcpu_run(vcpu, vmx);
 
        /*
         * We do not use IBRS in the kernel. If this vCPU has used the
@@ -6648,7 +6654,6 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu)
        vmx_recover_nmi_blocking(vmx);
        vmx_complete_interrupts(vmx);
 }
-STACK_FRAME_NON_STANDARD(vmx_vcpu_run);
 
 static struct kvm *vmx_vm_alloc(void)
 {
@@ -6816,7 +6821,7 @@ static int vmx_vm_init(struct kvm *kvm)
                         * Warn upon starting the first VM in a potentially
                         * insecure environment.
                         */
-                       if (cpu_smt_control == CPU_SMT_ENABLED)
+                       if (sched_smt_active())
                                pr_warn_once(L1TF_MSG_SMT);
                        if (l1tf_vmx_mitigation == VMENTER_L1D_FLUSH_NEVER)
                                pr_warn_once(L1TF_MSG_L1D);
@@ -7044,7 +7049,7 @@ static void update_intel_pt_cfg(struct kvm_vcpu *vcpu)
 
        /* unmask address range configure area */
        for (i = 0; i < vmx->pt_desc.addr_range; i++)
-               vmx->pt_desc.ctl_bitmask &= ~(0xf << (32 + i * 4));
+               vmx->pt_desc.ctl_bitmask &= ~(0xfULL << (32 + i * 4));
 }
 
 static void vmx_cpuid_update(struct kvm_vcpu *vcpu)
index 9932895..0ac0a64 100644 (file)
@@ -337,16 +337,16 @@ static inline int pi_test_and_set_pir(int vector, struct pi_desc *pi_desc)
        return test_and_set_bit(vector, (unsigned long *)pi_desc->pir);
 }
 
-static inline void pi_clear_sn(struct pi_desc *pi_desc)
+static inline void pi_set_sn(struct pi_desc *pi_desc)
 {
-       return clear_bit(POSTED_INTR_SN,
+       return set_bit(POSTED_INTR_SN,
                        (unsigned long *)&pi_desc->control);
 }
 
-static inline void pi_set_sn(struct pi_desc *pi_desc)
+static inline void pi_set_on(struct pi_desc *pi_desc)
 {
-       return set_bit(POSTED_INTR_SN,
-                       (unsigned long *)&pi_desc->control);
+       set_bit(POSTED_INTR_ON,
+               (unsigned long *)&pi_desc->control);
 }
 
 static inline void pi_clear_on(struct pi_desc *pi_desc)
index 02c8e09..941f932 100644 (file)
@@ -3834,6 +3834,8 @@ static int kvm_vcpu_ioctl_enable_cap(struct kvm_vcpu *vcpu,
        case KVM_CAP_HYPERV_SYNIC2:
                if (cap->args[0])
                        return -EINVAL;
+               /* fall through */
+
        case KVM_CAP_HYPERV_SYNIC:
                if (!irqchip_in_kernel(vcpu->kvm))
                        return -EINVAL;
@@ -5114,6 +5116,13 @@ int kvm_read_guest_virt(struct kvm_vcpu *vcpu,
 {
        u32 access = (kvm_x86_ops->get_cpl(vcpu) == 3) ? PFERR_USER_MASK : 0;
 
+       /*
+        * FIXME: this should call handle_emulation_failure if X86EMUL_IO_NEEDED
+        * is returned, but our callers are not ready for that and they blindly
+        * call kvm_inject_page_fault.  Ensure that they at least do not leak
+        * uninitialized kernel stack memory into cr2 and error code.
+        */
+       memset(exception, 0, sizeof(*exception));
        return kvm_read_guest_virt_helper(addr, val, bytes, vcpu, access,
                                          exception);
 }
@@ -6480,8 +6489,7 @@ restart:
                toggle_interruptibility(vcpu, ctxt->interruptibility);
                vcpu->arch.emulate_regs_need_sync_to_vcpu = false;
                kvm_rip_write(vcpu, ctxt->eip);
-               if (r == EMULATE_DONE &&
-                   (ctxt->tf || (vcpu->guest_debug & KVM_GUESTDBG_SINGLESTEP)))
+               if (r == EMULATE_DONE && ctxt->tf)
                        kvm_vcpu_do_singlestep(vcpu, &r);
                if (!ctxt->have_exception ||
                    exception_type(ctxt->exception.vector) == EXCPT_TRAP)
@@ -7093,10 +7101,10 @@ int kvm_emulate_hypercall(struct kvm_vcpu *vcpu)
        case KVM_HC_CLOCK_PAIRING:
                ret = kvm_pv_clock_pairing(vcpu, a0, a1);
                break;
+#endif
        case KVM_HC_SEND_IPI:
                ret = kvm_pv_send_ipi(vcpu->kvm, a0, a1, a2, a3, op_64_bit);
                break;
-#endif
        default:
                ret = -KVM_ENOSYS;
                break;
@@ -7793,7 +7801,7 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu)
         * 1) We should set ->mode before checking ->requests.  Please see
         * the comment in kvm_vcpu_exiting_guest_mode().
         *
-        * 2) For APICv, we should set ->mode before checking PIR.ON.  This
+        * 2) For APICv, we should set ->mode before checking PID.ON. This
         * pairs with the memory barrier implicit in pi_test_and_set_on
         * (see vmx_deliver_posted_interrupt).
         *
@@ -7937,6 +7945,7 @@ static inline int vcpu_block(struct kvm *kvm, struct kvm_vcpu *vcpu)
                vcpu->arch.pv.pv_unhalted = false;
                vcpu->arch.mp_state =
                        KVM_MP_STATE_RUNNABLE;
+               /* fall through */
        case KVM_MP_STATE_RUNNABLE:
                vcpu->arch.apf.halted = false;
                break;
index 6689467..df50451 100644 (file)
@@ -2,8 +2,11 @@
 #include <linux/module.h>
 #include <linux/io.h>
 
+#define movs(type,to,from) \
+       asm volatile("movs" type:"=&D" (to), "=&S" (from):"0" (to), "1" (from):"memory")
+
 /* Originally from i386/string.h */
-static __always_inline void __iomem_memcpy(void *to, const void *from, size_t n)
+static __always_inline void rep_movs(void *to, const void *from, size_t n)
 {
        unsigned long d0, d1, d2;
        asm volatile("rep ; movsl\n\t"
@@ -21,13 +24,37 @@ static __always_inline void __iomem_memcpy(void *to, const void *from, size_t n)
 
 void memcpy_fromio(void *to, const volatile void __iomem *from, size_t n)
 {
-       __iomem_memcpy(to, (const void *)from, n);
+       if (unlikely(!n))
+               return;
+
+       /* Align any unaligned source IO */
+       if (unlikely(1 & (unsigned long)from)) {
+               movs("b", to, from);
+               n--;
+       }
+       if (n > 1 && unlikely(2 & (unsigned long)from)) {
+               movs("w", to, from);
+               n-=2;
+       }
+       rep_movs(to, (const void *)from, n);
 }
 EXPORT_SYMBOL(memcpy_fromio);
 
 void memcpy_toio(volatile void __iomem *to, const void *from, size_t n)
 {
-       __iomem_memcpy((void *)to, (const void *) from, n);
+       if (unlikely(!n))
+               return;
+
+       /* Align any unaligned destination IO */
+       if (unlikely(1 & (unsigned long)to)) {
+               movs("b", to, from);
+               n--;
+       }
+       if (n > 1 && unlikely(2 & (unsigned long)to)) {
+               movs("w", to, from);
+               n-=2;
+       }
+       rep_movs((void *)to, (const void *) from, n);
 }
 EXPORT_SYMBOL(memcpy_toio);
 
index 79778ab..a536651 100644 (file)
@@ -36,8 +36,8 @@ static inline u16 i8254(void)
        u16 status, timer;
 
        do {
-               outb(I8254_PORT_CONTROL,
-                    I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
+               outb(I8254_CMD_READBACK | I8254_SELECT_COUNTER0,
+                    I8254_PORT_CONTROL);
                status = inb(I8254_PORT_COUNTER0);
                timer  = inb(I8254_PORT_COUNTER0);
                timer |= inb(I8254_PORT_COUNTER0) << 8;
index 2ff25ad..9d5c75f 100644 (file)
@@ -595,7 +595,7 @@ static void show_ldttss(const struct desc_ptr *gdt, const char *name, u16 index)
                return;
        }
 
-       addr = desc.base0 | (desc.base1 << 16) | (desc.base2 << 24);
+       addr = desc.base0 | (desc.base1 << 16) | ((unsigned long)desc.base2 << 24);
 #ifdef CONFIG_X86_64
        addr |= ((u64)desc.base3 << 32);
 #endif
index a19ef1a..4aa9b14 100644 (file)
@@ -158,8 +158,8 @@ static void __init sme_populate_pgd(struct sme_populate_pgd_data *ppd)
        pmd = pmd_offset(pud, ppd->vaddr);
        if (pmd_none(*pmd)) {
                pte = ppd->pgtable_area;
-               memset(pte, 0, sizeof(pte) * PTRS_PER_PTE);
-               ppd->pgtable_area += sizeof(pte) * PTRS_PER_PTE;
+               memset(pte, 0, sizeof(*pte) * PTRS_PER_PTE);
+               ppd->pgtable_area += sizeof(*pte) * PTRS_PER_PTE;
                set_pmd(pmd, __pmd(PMD_FLAGS | __pa(pte)));
        }
 
index 4f89723..14e6119 100644 (file)
@@ -230,6 +230,29 @@ static bool __cpa_pfn_in_highmap(unsigned long pfn)
 
 #endif
 
+/*
+ * See set_mce_nospec().
+ *
+ * Machine check recovery code needs to change cache mode of poisoned pages to
+ * UC to avoid speculative access logging another error. But passing the
+ * address of the 1:1 mapping to set_memory_uc() is a fine way to encourage a
+ * speculative access. So we cheat and flip the top bit of the address. This
+ * works fine for the code that updates the page tables. But at the end of the
+ * process we need to flush the TLB and cache and the non-canonical address
+ * causes a #GP fault when used by the INVLPG and CLFLUSH instructions.
+ *
+ * But in the common case we already have a canonical address. This code
+ * will fix the top bit if needed and is a no-op otherwise.
+ */
+static inline unsigned long fix_addr(unsigned long addr)
+{
+#ifdef CONFIG_X86_64
+       return (long)(addr << 1) >> 1;
+#else
+       return addr;
+#endif
+}
+
 static unsigned long __cpa_addr(struct cpa_data *cpa, unsigned long idx)
 {
        if (cpa->flags & CPA_PAGES_ARRAY) {
@@ -313,7 +336,7 @@ void __cpa_flush_tlb(void *data)
        unsigned int i;
 
        for (i = 0; i < cpa->numpages; i++)
-               __flush_tlb_one_kernel(__cpa_addr(cpa, i));
+               __flush_tlb_one_kernel(fix_addr(__cpa_addr(cpa, i)));
 }
 
 static void cpa_flush(struct cpa_data *data, int cache)
@@ -347,7 +370,7 @@ static void cpa_flush(struct cpa_data *data, int cache)
                 * Only flush present addresses:
                 */
                if (pte && (pte_val(*pte) & _PAGE_PRESENT))
-                       clflush_cache_range_opt((void *)addr, PAGE_SIZE);
+                       clflush_cache_range_opt((void *)fix_addr(addr), PAGE_SIZE);
        }
        mb();
 }
@@ -1627,29 +1650,6 @@ out:
        return ret;
 }
 
-/*
- * Machine check recovery code needs to change cache mode of poisoned
- * pages to UC to avoid speculative access logging another error. But
- * passing the address of the 1:1 mapping to set_memory_uc() is a fine
- * way to encourage a speculative access. So we cheat and flip the top
- * bit of the address. This works fine for the code that updates the
- * page tables. But at the end of the process we need to flush the cache
- * and the non-canonical address causes a #GP fault when used by the
- * CLFLUSH instruction.
- *
- * But in the common case we already have a canonical address. This code
- * will fix the top bit if needed and is a no-op otherwise.
- */
-static inline unsigned long make_addr_canonical_again(unsigned long addr)
-{
-#ifdef CONFIG_X86_64
-       return (long)(addr << 1) >> 1;
-#else
-       return addr;
-#endif
-}
-
-
 static int change_page_attr_set_clr(unsigned long *addr, int numpages,
                                    pgprot_t mask_set, pgprot_t mask_clr,
                                    int force_split, int in_flag,
index 4a6a5a2..eb33432 100644 (file)
@@ -29,7 +29,8 @@
 
 struct uv_systab *uv_systab;
 
-s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
+static s64 __uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
+                       u64 a4, u64 a5)
 {
        struct uv_systab *tab = uv_systab;
        s64 ret;
@@ -51,6 +52,19 @@ s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
 
        return ret;
 }
+
+s64 uv_bios_call(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3, u64 a4, u64 a5)
+{
+       s64 ret;
+
+       if (down_interruptible(&__efi_uv_runtime_lock))
+               return BIOS_STATUS_ABORT;
+
+       ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
+       up(&__efi_uv_runtime_lock);
+
+       return ret;
+}
 EXPORT_SYMBOL_GPL(uv_bios_call);
 
 s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
@@ -59,10 +73,15 @@ s64 uv_bios_call_irqsave(enum uv_bios_cmd which, u64 a1, u64 a2, u64 a3,
        unsigned long bios_flags;
        s64 ret;
 
+       if (down_interruptible(&__efi_uv_runtime_lock))
+               return BIOS_STATUS_ABORT;
+
        local_irq_save(bios_flags);
-       ret = uv_bios_call(which, a1, a2, a3, a4, a5);
+       ret = __uv_bios_call(which, a1, a2, a3, a4, a5);
        local_irq_restore(bios_flags);
 
+       up(&__efi_uv_runtime_lock);
+
        return ret;
 }
 
index 2f6787f..c54a493 100644 (file)
@@ -898,10 +898,7 @@ static u64 xen_read_msr_safe(unsigned int msr, int *err)
        val = native_read_msr_safe(msr, err);
        switch (msr) {
        case MSR_IA32_APICBASE:
-#ifdef CONFIG_X86_X2APIC
-               if (!(cpuid_ecx(1) & (1 << (X86_FEATURE_X2APIC & 31))))
-#endif
-                       val &= ~X2APIC_ENABLE;
+               val &= ~X2APIC_ENABLE;
                break;
        }
        return val;
index 72bf446..6e29794 100644 (file)
@@ -361,8 +361,6 @@ void xen_timer_resume(void)
 {
        int cpu;
 
-       pvclock_resume();
-
        if (xen_clockevent != &xen_vcpuop_clockevent)
                return;
 
@@ -379,12 +377,15 @@ static const struct pv_time_ops xen_time_ops __initconst = {
 };
 
 static struct pvclock_vsyscall_time_info *xen_clock __read_mostly;
+static u64 xen_clock_value_saved;
 
 void xen_save_time_memory_area(void)
 {
        struct vcpu_register_time_memory_area t;
        int ret;
 
+       xen_clock_value_saved = xen_clocksource_read() - xen_sched_clock_offset;
+
        if (!xen_clock)
                return;
 
@@ -404,7 +405,7 @@ void xen_restore_time_memory_area(void)
        int ret;
 
        if (!xen_clock)
-               return;
+               goto out;
 
        t.addr.v = &xen_clock->pvti;
 
@@ -421,6 +422,11 @@ void xen_restore_time_memory_area(void)
        if (ret != 0)
                pr_notice("Cannot restore secondary vcpu_time_info (err %d)",
                          ret);
+
+out:
+       /* Need pvclock_resume() before using xen_clocksource_read(). */
+       pvclock_resume();
+       xen_sched_clock_offset = xen_clocksource_read() - xen_clock_value_saved;
 }
 
 static void xen_setup_vsyscall_time_info(void)
index 20a0756..ce91682 100644 (file)
@@ -164,7 +164,7 @@ config XTENSA_FAKE_NMI
          If unsure, say N.
 
 config XTENSA_UNALIGNED_USER
-       bool "Unaligned memory access in use space"
+       bool "Unaligned memory access in user space"
        help
          The Xtensa architecture currently does not handle unaligned
          memory accesses in hardware but through an exception handler.
@@ -451,7 +451,7 @@ config USE_OF
        help
          Include support for flattened device tree machine descriptions.
 
-config BUILTIN_DTB
+config BUILTIN_DTB_SOURCE
        string "DTB to build into the kernel image"
        depends on OF
 
index f8052ba..0b8d00c 100644 (file)
@@ -7,9 +7,9 @@
 #
 #
 
-BUILTIN_DTB := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB)).dtb.o
-ifneq ($(CONFIG_BUILTIN_DTB),"")
-obj-$(CONFIG_OF) += $(BUILTIN_DTB)
+BUILTIN_DTB_SOURCE := $(patsubst "%",%,$(CONFIG_BUILTIN_DTB_SOURCE)).dtb.o
+ifneq ($(CONFIG_BUILTIN_DTB_SOURCE),"")
+obj-$(CONFIG_OF) += $(BUILTIN_DTB_SOURCE)
 endif
 
 # for CONFIG_OF_ALL_DTBS test
index 2bf964d..f378e56 100644 (file)
@@ -34,7 +34,7 @@ CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="earlycon=uart8250,mmio32native,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=0x38000000@0"
 CONFIG_USE_OF=y
-CONFIG_BUILTIN_DTB="kc705"
+CONFIG_BUILTIN_DTB_SOURCE="kc705"
 # CONFIG_COMPACTION is not set
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_PM=y
index 3221b70..62f32a9 100644 (file)
@@ -38,7 +38,7 @@ CONFIG_HIGHMEM=y
 # CONFIG_PCI is not set
 CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_USE_OF=y
-CONFIG_BUILTIN_DTB="csp"
+CONFIG_BUILTIN_DTB_SOURCE="csp"
 # CONFIG_COMPACTION is not set
 CONFIG_XTFPGA_LCD=y
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
index 985fa85..8bebe07 100644 (file)
@@ -33,7 +33,7 @@ CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="earlycon=uart8250,mmio32native,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=0x38000000@0"
 CONFIG_USE_OF=y
-CONFIG_BUILTIN_DTB="kc705"
+CONFIG_BUILTIN_DTB_SOURCE="kc705"
 # CONFIG_COMPACTION is not set
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_NET=y
index f3fc4f9..933ab2a 100644 (file)
@@ -39,7 +39,7 @@ CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="earlycon=uart8250,mmio32native,0x9d050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=256M@0x60000000"
 CONFIG_USE_OF=y
-CONFIG_BUILTIN_DTB="kc705_nommu"
+CONFIG_BUILTIN_DTB_SOURCE="kc705_nommu"
 CONFIG_BINFMT_FLAT=y
 CONFIG_NET=y
 CONFIG_PACKET=y
index 11fed6c..e29c5b1 100644 (file)
@@ -33,11 +33,12 @@ CONFIG_SMP=y
 CONFIG_HOTPLUG_CPU=y
 # CONFIG_INITIALIZE_XTENSA_MMU_INSIDE_VMLINUX is not set
 # CONFIG_PCI is not set
+CONFIG_VECTORS_OFFSET=0x00002000
 CONFIG_XTENSA_PLATFORM_XTFPGA=y
 CONFIG_CMDLINE_BOOL=y
 CONFIG_CMDLINE="earlycon=uart8250,mmio32native,0xfd050020,115200n8 console=ttyS0,115200n8 ip=dhcp root=/dev/nfs rw debug memmap=96M@0"
 CONFIG_USE_OF=y
-CONFIG_BUILTIN_DTB="lx200mx"
+CONFIG_BUILTIN_DTB_SOURCE="lx200mx"
 # CONFIG_COMPACTION is not set
 # CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS is not set
 CONFIG_NET=y
index da08e75..7f00971 100644 (file)
@@ -276,12 +276,13 @@ should_never_return:
 
        movi    a2, cpu_start_ccount
 1:
+       memw
        l32i    a3, a2, 0
        beqi    a3, 0, 1b
        movi    a3, 0
        s32i    a3, a2, 0
-       memw
 1:
+       memw
        l32i    a3, a2, 0
        beqi    a3, 0, 1b
        wsr     a3, ccount
@@ -317,11 +318,13 @@ ENTRY(cpu_restart)
        rsr     a0, prid
        neg     a2, a0
        movi    a3, cpu_start_id
+       memw
        s32i    a2, a3, 0
 #if XCHAL_DCACHE_IS_WRITEBACK
        dhwbi   a3, 0
 #endif
 1:
+       memw
        l32i    a2, a3, 0
        dhi     a3, 0
        bne     a2, a0, 1b
index 932d646..be1f280 100644 (file)
@@ -83,7 +83,7 @@ void __init smp_prepare_cpus(unsigned int max_cpus)
 {
        unsigned i;
 
-       for (i = 0; i < max_cpus; ++i)
+       for_each_possible_cpu(i)
                set_cpu_present(i, true);
 }
 
@@ -96,6 +96,11 @@ void __init smp_init_cpus(void)
        pr_info("%s: Core Count = %d\n", __func__, ncpus);
        pr_info("%s: Core Id = %d\n", __func__, core_id);
 
+       if (ncpus > NR_CPUS) {
+               ncpus = NR_CPUS;
+               pr_info("%s: limiting core count by %d\n", __func__, ncpus);
+       }
+
        for (i = 0; i < ncpus; ++i)
                set_cpu_possible(i, true);
 }
@@ -195,9 +200,11 @@ static int boot_secondary(unsigned int cpu, struct task_struct *ts)
        int i;
 
 #ifdef CONFIG_HOTPLUG_CPU
-       cpu_start_id = cpu;
-       system_flush_invalidate_dcache_range(
-                       (unsigned long)&cpu_start_id, sizeof(cpu_start_id));
+       WRITE_ONCE(cpu_start_id, cpu);
+       /* Pairs with the third memw in the cpu_restart */
+       mb();
+       system_flush_invalidate_dcache_range((unsigned long)&cpu_start_id,
+                                            sizeof(cpu_start_id));
 #endif
        smp_call_function_single(0, mx_cpu_start, (void *)cpu, 1);
 
@@ -206,18 +213,21 @@ static int boot_secondary(unsigned int cpu, struct task_struct *ts)
                        ccount = get_ccount();
                while (!ccount);
 
-               cpu_start_ccount = ccount;
+               WRITE_ONCE(cpu_start_ccount, ccount);
 
-               while (time_before(jiffies, timeout)) {
+               do {
+                       /*
+                        * Pairs with the first two memws in the
+                        * .Lboot_secondary.
+                        */
                        mb();
-                       if (!cpu_start_ccount)
-                               break;
-               }
+                       ccount = READ_ONCE(cpu_start_ccount);
+               } while (ccount && time_before(jiffies, timeout));
 
-               if (cpu_start_ccount) {
+               if (ccount) {
                        smp_call_function_single(0, mx_cpu_stop,
-                                       (void *)cpu, 1);
-                       cpu_start_ccount = 0;
+                                                (void *)cpu, 1);
+                       WRITE_ONCE(cpu_start_ccount, 0);
                        return -EIO;
                }
        }
@@ -237,6 +247,7 @@ int __cpu_up(unsigned int cpu, struct task_struct *idle)
        pr_debug("%s: Calling wakeup_secondary(cpu:%d, idle:%p, sp: %08lx)\n",
                        __func__, cpu, idle, start_info.stack);
 
+       init_completion(&cpu_running);
        ret = boot_secondary(cpu, idle);
        if (ret == 0) {
                wait_for_completion_timeout(&cpu_running,
@@ -298,8 +309,10 @@ void __cpu_die(unsigned int cpu)
        unsigned long timeout = jiffies + msecs_to_jiffies(1000);
        while (time_before(jiffies, timeout)) {
                system_invalidate_dcache_range((unsigned long)&cpu_start_id,
-                               sizeof(cpu_start_id));
-               if (cpu_start_id == -cpu) {
+                                              sizeof(cpu_start_id));
+               /* Pairs with the second memw in the cpu_restart */
+               mb();
+               if (READ_ONCE(cpu_start_id) == -cpu) {
                        platform_cpu_kill(cpu);
                        return;
                }
index fd524a5..378186b 100644 (file)
@@ -89,7 +89,7 @@ static int ccount_timer_shutdown(struct clock_event_device *evt)
                container_of(evt, struct ccount_timer, evt);
 
        if (timer->irq_enabled) {
-               disable_irq(evt->irq);
+               disable_irq_nosync(evt->irq);
                timer->irq_enabled = 0;
        }
        return 0;
index 63e0f12..72adbbe 100644 (file)
@@ -1154,15 +1154,14 @@ static void bfq_activate_requeue_entity(struct bfq_entity *entity,
 }
 
 /**
- * __bfq_deactivate_entity - deactivate an entity from its service tree.
- * @entity: the entity to deactivate.
+ * __bfq_deactivate_entity - update sched_data and service trees for
+ * entity, so as to represent entity as inactive
+ * @entity: the entity being deactivated.
  * @ins_into_idle_tree: if false, the entity will not be put into the
  *                     idle tree.
  *
- * Deactivates an entity, independently of its previous state.  Must
- * be invoked only if entity is on a service tree. Extracts the entity
- * from that tree, and if necessary and allowed, puts it into the idle
- * tree.
+ * If necessary and allowed, puts entity into the idle tree. NOTE:
+ * entity may be on no tree if in service.
  */
 bool __bfq_deactivate_entity(struct bfq_entity *entity, bool ins_into_idle_tree)
 {
index c780429..6b78ec5 100644 (file)
@@ -462,6 +462,10 @@ static void blk_rq_timed_out_timer(struct timer_list *t)
        kblockd_schedule_work(&q->timeout_work);
 }
 
+static void blk_timeout_work(struct work_struct *work)
+{
+}
+
 /**
  * blk_alloc_queue_node - allocate a request queue
  * @gfp_mask: memory allocation flags
@@ -505,7 +509,7 @@ struct request_queue *blk_alloc_queue_node(gfp_t gfp_mask, int node_id)
        timer_setup(&q->backing_dev_info->laptop_mode_wb_timer,
                    laptop_mode_timer_fn, 0);
        timer_setup(&q->timeout, blk_rq_timed_out_timer, 0);
-       INIT_WORK(&q->timeout_work, NULL);
+       INIT_WORK(&q->timeout_work, blk_timeout_work);
        INIT_LIST_HEAD(&q->icq_list);
 #ifdef CONFIG_BLK_CGROUP
        INIT_LIST_HEAD(&q->blkg_list);
@@ -661,7 +665,6 @@ no_merge:
  * blk_attempt_plug_merge - try to merge with %current's plugged list
  * @q: request_queue new bio is being queued at
  * @bio: new bio being queued
- * @request_count: out parameter for number of traversed plugged requests
  * @same_queue_rq: pointer to &struct request that gets filled in when
  * another request associated with @q is found on the plug list
  * (optional, may be %NULL)
@@ -1683,6 +1686,15 @@ EXPORT_SYMBOL(kblockd_mod_delayed_work_on);
  * @plug:      The &struct blk_plug that needs to be initialized
  *
  * Description:
+ *   blk_start_plug() indicates to the block layer an intent by the caller
+ *   to submit multiple I/O requests in a batch.  The block layer may use
+ *   this hint to defer submitting I/Os from the caller until blk_finish_plug()
+ *   is called.  However, the block layer may choose to submit requests
+ *   before a call to blk_finish_plug() if the number of queued I/Os
+ *   exceeds %BLK_MAX_REQUEST_COUNT, or if the size of the I/O is larger than
+ *   %BLK_PLUG_FLUSH_SIZE.  The queued I/Os may also be submitted early if
+ *   the task schedules (see below).
+ *
  *   Tracking blk_plug inside the task_struct will help with auto-flushing the
  *   pending I/O should the task end up blocking between blk_start_plug() and
  *   blk_finish_plug(). This is important from a performance perspective, but
@@ -1765,6 +1777,16 @@ void blk_flush_plug_list(struct blk_plug *plug, bool from_schedule)
                blk_mq_flush_plug_list(plug, from_schedule);
 }
 
+/**
+ * blk_finish_plug - mark the end of a batch of submitted I/O
+ * @plug:      The &struct blk_plug passed to blk_start_plug()
+ *
+ * Description:
+ * Indicate that a batch of I/O submissions is complete.  This function
+ * must be paired with an initial call to blk_start_plug().  The intent
+ * is to allow the block layer to optimize I/O submission.  See the
+ * documentation for blk_start_plug() for more information.
+ */
 void blk_finish_plug(struct blk_plug *plug)
 {
        if (plug != current->plug)
index a3fc719..6e0f2d9 100644 (file)
@@ -335,7 +335,7 @@ static void mq_flush_data_end_io(struct request *rq, blk_status_t error)
        blk_flush_complete_seq(rq, fq, REQ_FSEQ_DATA, error);
        spin_unlock_irqrestore(&fq->mq_flush_lock, flags);
 
-       blk_mq_run_hw_queue(hctx, true);
+       blk_mq_sched_restart(hctx);
 }
 
 /**
index fc714ef..2620baa 100644 (file)
@@ -72,6 +72,7 @@
 #include <linux/sched/loadavg.h>
 #include <linux/sched/signal.h>
 #include <trace/events/block.h>
+#include <linux/blk-mq.h>
 #include "blk-rq-qos.h"
 #include "blk-stat.h"
 
@@ -591,6 +592,7 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio)
        u64 now = ktime_to_ns(ktime_get());
        bool issue_as_root = bio_issue_as_root_blkg(bio);
        bool enabled = false;
+       int inflight = 0;
 
        blkg = bio->bi_blkg;
        if (!blkg || !bio_flagged(bio, BIO_TRACKED))
@@ -601,6 +603,9 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio)
                return;
 
        enabled = blk_iolatency_enabled(iolat->blkiolat);
+       if (!enabled)
+               return;
+
        while (blkg && blkg->parent) {
                iolat = blkg_to_lat(blkg);
                if (!iolat) {
@@ -609,8 +614,9 @@ static void blkcg_iolatency_done_bio(struct rq_qos *rqos, struct bio *bio)
                }
                rqw = &iolat->rq_wait;
 
-               atomic_dec(&rqw->inflight);
-               if (!enabled || iolat->min_lat_nsec == 0)
+               inflight = atomic_dec_return(&rqw->inflight);
+               WARN_ON_ONCE(inflight < 0);
+               if (iolat->min_lat_nsec == 0)
                        goto next;
                iolatency_record_time(iolat, &bio->bi_issue, now,
                                      issue_as_root);
@@ -754,10 +760,13 @@ int blk_iolatency_init(struct request_queue *q)
        return 0;
 }
 
-static void iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val)
+/*
+ * return 1 for enabling iolatency, return -1 for disabling iolatency, otherwise
+ * return 0.
+ */
+static int iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val)
 {
        struct iolatency_grp *iolat = blkg_to_lat(blkg);
-       struct blk_iolatency *blkiolat = iolat->blkiolat;
        u64 oldval = iolat->min_lat_nsec;
 
        iolat->min_lat_nsec = val;
@@ -766,9 +775,10 @@ static void iolatency_set_min_lat_nsec(struct blkcg_gq *blkg, u64 val)
                                    BLKIOLATENCY_MAX_WIN_SIZE);
 
        if (!oldval && val)
-               atomic_inc(&blkiolat->enabled);
+               return 1;
        if (oldval && !val)
-               atomic_dec(&blkiolat->enabled);
+               return -1;
+       return 0;
 }
 
 static void iolatency_clear_scaling(struct blkcg_gq *blkg)
@@ -800,6 +810,7 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
        u64 lat_val = 0;
        u64 oldval;
        int ret;
+       int enable = 0;
 
        ret = blkg_conf_prep(blkcg, &blkcg_policy_iolatency, buf, &ctx);
        if (ret)
@@ -834,7 +845,12 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
        blkg = ctx.blkg;
        oldval = iolat->min_lat_nsec;
 
-       iolatency_set_min_lat_nsec(blkg, lat_val);
+       enable = iolatency_set_min_lat_nsec(blkg, lat_val);
+       if (enable) {
+               WARN_ON_ONCE(!blk_get_queue(blkg->q));
+               blkg_get(blkg);
+       }
+
        if (oldval != iolat->min_lat_nsec) {
                iolatency_clear_scaling(blkg);
        }
@@ -842,6 +858,24 @@ static ssize_t iolatency_set_limit(struct kernfs_open_file *of, char *buf,
        ret = 0;
 out:
        blkg_conf_finish(&ctx);
+       if (ret == 0 && enable) {
+               struct iolatency_grp *tmp = blkg_to_lat(blkg);
+               struct blk_iolatency *blkiolat = tmp->blkiolat;
+
+               blk_mq_freeze_queue(blkg->q);
+
+               if (enable == 1)
+                       atomic_inc(&blkiolat->enabled);
+               else if (enable == -1)
+                       atomic_dec(&blkiolat->enabled);
+               else
+                       WARN_ON_ONCE(1);
+
+               blk_mq_unfreeze_queue(blkg->q);
+
+               blkg_put(blkg);
+               blk_put_queue(blkg->q);
+       }
        return ret ?: nbytes;
 }
 
@@ -977,8 +1011,14 @@ static void iolatency_pd_offline(struct blkg_policy_data *pd)
 {
        struct iolatency_grp *iolat = pd_to_lat(pd);
        struct blkcg_gq *blkg = lat_to_blkg(iolat);
+       struct blk_iolatency *blkiolat = iolat->blkiolat;
+       int ret;
 
-       iolatency_set_min_lat_nsec(blkg, 0);
+       ret = iolatency_set_min_lat_nsec(blkg, 0);
+       if (ret == 1)
+               atomic_inc(&blkiolat->enabled);
+       if (ret == -1)
+               atomic_dec(&blkiolat->enabled);
        iolatency_clear_scaling(blkg);
 }
 
index fb2c82c..038cb62 100644 (file)
@@ -1,8 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2017 Western Digital Corporation or its affiliates.
- *
- * This file is released under the GPL.
  */
 
 #include <linux/blkdev.h>
index 90d6876..7921573 100644 (file)
@@ -308,8 +308,9 @@ static const char *const cmd_flag_name[] = {
        CMD_FLAG_NAME(PREFLUSH),
        CMD_FLAG_NAME(RAHEAD),
        CMD_FLAG_NAME(BACKGROUND),
-       CMD_FLAG_NAME(NOUNMAP),
        CMD_FLAG_NAME(NOWAIT),
+       CMD_FLAG_NAME(NOUNMAP),
+       CMD_FLAG_NAME(HIPRI),
 };
 #undef CMD_FLAG_NAME
 
@@ -838,6 +839,9 @@ static const struct blk_mq_debugfs_attr blk_mq_debugfs_ctx_attrs[] = {
 static bool debugfs_create_files(struct dentry *parent, void *data,
                                 const struct blk_mq_debugfs_attr *attr)
 {
+       if (IS_ERR_OR_NULL(parent))
+               return false;
+
        d_inode(parent)->i_private = data;
 
        for (; attr->name; attr++) {
index 3ba37b9..9437a5e 100644 (file)
@@ -737,12 +737,20 @@ static void blk_mq_requeue_work(struct work_struct *work)
        spin_unlock_irq(&q->requeue_lock);
 
        list_for_each_entry_safe(rq, next, &rq_list, queuelist) {
-               if (!(rq->rq_flags & RQF_SOFTBARRIER))
+               if (!(rq->rq_flags & (RQF_SOFTBARRIER | RQF_DONTPREP)))
                        continue;
 
                rq->rq_flags &= ~RQF_SOFTBARRIER;
                list_del_init(&rq->queuelist);
-               blk_mq_sched_insert_request(rq, true, false, false);
+               /*
+                * If RQF_DONTPREP, rq has contained some driver specific
+                * data, so insert it to hctx dispatch list to avoid any
+                * merge.
+                */
+               if (rq->rq_flags & RQF_DONTPREP)
+                       blk_mq_request_bypass_insert(rq, false);
+               else
+                       blk_mq_sched_insert_request(rq, true, false, false);
        }
 
        while (!list_empty(&rq_list)) {
@@ -1906,7 +1914,7 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
 {
        const int is_sync = op_is_sync(bio->bi_opf);
        const int is_flush_fua = op_is_flush(bio->bi_opf);
-       struct blk_mq_alloc_data data = { .flags = 0, .cmd_flags = bio->bi_opf };
+       struct blk_mq_alloc_data data = { .flags = 0};
        struct request *rq;
        struct blk_plug *plug;
        struct request *same_queue_rq = NULL;
@@ -1928,6 +1936,7 @@ static blk_qc_t blk_mq_make_request(struct request_queue *q, struct bio *bio)
 
        rq_qos_throttle(q, bio);
 
+       data.cmd_flags = bio->bi_opf;
        rq = blk_mq_get_request(q, bio, &data);
        if (unlikely(!rq)) {
                rq_qos_cleanup(q, bio);
index d943d46..d0b3dd5 100644 (file)
@@ -36,7 +36,6 @@ struct blk_mq_ctx {
        struct kobject          kobj;
 } ____cacheline_aligned_in_smp;
 
-void blk_mq_freeze_queue(struct request_queue *q);
 void blk_mq_free_queue(struct request_queue *q);
 int blk_mq_update_nr_requests(struct request_queue *q, unsigned int nr);
 void blk_mq_wake_waiters(struct request_queue *q);
index f0c5664..fd166fb 100644 (file)
@@ -597,7 +597,7 @@ static void wbt_track(struct rq_qos *rqos, struct request *rq, struct bio *bio)
        rq->wbt_flags |= bio_to_wbt_flags(rwb, bio);
 }
 
-void wbt_issue(struct rq_qos *rqos, struct request *rq)
+static void wbt_issue(struct rq_qos *rqos, struct request *rq)
 {
        struct rq_wb *rwb = RQWB(rqos);
 
@@ -617,7 +617,7 @@ void wbt_issue(struct rq_qos *rqos, struct request *rq)
        }
 }
 
-void wbt_requeue(struct rq_qos *rqos, struct request *rq)
+static void wbt_requeue(struct rq_qos *rqos, struct request *rq)
 {
        struct rq_wb *rwb = RQWB(rqos);
        if (!rwb_enabled(rwb))
index 6651e71..5564e73 100644 (file)
@@ -539,6 +539,8 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
        ictx = skcipher_instance_ctx(inst);
 
        /* Stream cipher, e.g. "xchacha12" */
+       crypto_set_skcipher_spawn(&ictx->streamcipher_spawn,
+                                 skcipher_crypto_instance(inst));
        err = crypto_grab_skcipher(&ictx->streamcipher_spawn, streamcipher_name,
                                   0, crypto_requires_sync(algt->type,
                                                           algt->mask));
@@ -547,6 +549,8 @@ static int adiantum_create(struct crypto_template *tmpl, struct rtattr **tb)
        streamcipher_alg = crypto_spawn_skcipher_alg(&ictx->streamcipher_spawn);
 
        /* Block cipher, e.g. "aes" */
+       crypto_set_spawn(&ictx->blockcipher_spawn,
+                        skcipher_crypto_instance(inst));
        err = crypto_grab_spawn(&ictx->blockcipher_spawn, blockcipher_name,
                                CRYPTO_ALG_TYPE_CIPHER, CRYPTO_ALG_TYPE_MASK);
        if (err)
index 17eb09d..ec78a04 100644 (file)
@@ -122,8 +122,10 @@ static void alg_do_release(const struct af_alg_type *type, void *private)
 
 int af_alg_release(struct socket *sock)
 {
-       if (sock->sk)
+       if (sock->sk) {
                sock_put(sock->sk);
+               sock->sk = NULL;
+       }
        return 0;
 }
 EXPORT_SYMBOL_GPL(af_alg_release);
index 37f54d1..4be293a 100644 (file)
@@ -58,14 +58,22 @@ int crypto_authenc_extractkeys(struct crypto_authenc_keys *keys, const u8 *key,
                return -EINVAL;
        if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
                return -EINVAL;
-       if (RTA_PAYLOAD(rta) < sizeof(*param))
+
+       /*
+        * RTA_OK() didn't align the rtattr's payload when validating that it
+        * fits in the buffer.  Yet, the keys should start on the next 4-byte
+        * aligned boundary.  To avoid confusion, require that the rtattr
+        * payload be exactly the param struct, which has a 4-byte aligned size.
+        */
+       if (RTA_PAYLOAD(rta) != sizeof(*param))
                return -EINVAL;
+       BUILD_BUG_ON(sizeof(*param) % RTA_ALIGNTO);
 
        param = RTA_DATA(rta);
        keys->enckeylen = be32_to_cpu(param->enckeylen);
 
-       key += RTA_ALIGN(rta->rta_len);
-       keylen -= RTA_ALIGN(rta->rta_len);
+       key += rta->rta_len;
+       keylen -= rta->rta_len;
 
        if (keylen < keys->enckeylen)
                return -EINVAL;
index 80a25cc..4741fe8 100644 (file)
@@ -279,7 +279,7 @@ static void authenc_esn_verify_ahash_done(struct crypto_async_request *areq,
        struct aead_request *req = areq->data;
 
        err = err ?: crypto_authenc_esn_decrypt_tail(req, 0);
-       aead_request_complete(req, err);
+       authenc_esn_request_complete(req, err);
 }
 
 static int crypto_authenc_esn_decrypt(struct aead_request *req)
index 9a5c60f..c0cf87a 100644 (file)
@@ -100,7 +100,7 @@ static void sm3_compress(u32 *w, u32 *wt, u32 *m)
 
        for (i = 0; i <= 63; i++) {
 
-               ss1 = rol32((rol32(a, 12) + e + rol32(t(i), i)), 7);
+               ss1 = rol32((rol32(a, 12) + e + rol32(t(i), i & 31)), 7);
 
                ss2 = ss1 ^ rol32(a, 12);
 
index 7b65a80..90ff0a4 100644 (file)
@@ -10,6 +10,7 @@ menuconfig ACPI
        bool "ACPI (Advanced Configuration and Power Interface) Support"
        depends on ARCH_SUPPORTS_ACPI
        select PNP
+       select NLS
        default y if X86
        help
          Advanced Configuration and Power Interface (ACPI) support for 
index 7c6afc1..bb85742 100644 (file)
@@ -41,7 +41,8 @@ acpi-y                                += ec.o
 acpi-$(CONFIG_ACPI_DOCK)       += dock.o
 acpi-$(CONFIG_PCI)             += pci_root.o pci_link.o pci_irq.o
 obj-$(CONFIG_ACPI_MCFG)                += pci_mcfg.o
-acpi-y                         += acpi_lpss.o acpi_apd.o
+acpi-$(CONFIG_PCI)             += acpi_lpss.o
+acpi-y                         += acpi_apd.o
 acpi-y                         += acpi_platform.o
 acpi-y                         += acpi_pnp.o
 acpi-$(CONFIG_ARM_AMBA)        += acpi_amba.o
index 5f94c35..1e2a10a 100644 (file)
@@ -18,7 +18,7 @@
 #include <linux/mutex.h>
 #include <linux/pci.h>
 #include <linux/platform_device.h>
-#include <linux/platform_data/clk-lpss.h>
+#include <linux/platform_data/x86/clk-lpss.h>
 #include <linux/platform_data/x86/pmc_atom.h>
 #include <linux/pm_domain.h>
 #include <linux/pm_runtime.h>
index fdd90ff..e48894e 100644 (file)
@@ -876,7 +876,7 @@ int iort_iommu_msi_get_resv_regions(struct device *dev, struct list_head *head)
        return (resv == its->its_count) ? resv : -ENODEV;
 }
 #else
-static inline const struct iommu_ops *iort_fwspec_iommu_ops(struct device *dev);
+static inline const struct iommu_ops *iort_fwspec_iommu_ops(struct device *dev)
 { return NULL; }
 static inline int iort_add_device_replay(const struct iommu_ops *ops,
                                         struct device *dev)
@@ -952,9 +952,10 @@ static int rc_dma_get_range(struct device *dev, u64 *size)
 {
        struct acpi_iort_node *node;
        struct acpi_iort_root_complex *rc;
+       struct pci_bus *pbus = to_pci_dev(dev)->bus;
 
        node = iort_scan_node(ACPI_IORT_NODE_PCI_ROOT_COMPLEX,
-                             iort_match_node_callback, dev);
+                             iort_match_node_callback, &pbus->dev);
        if (!node || node->revision < 1)
                return -ENODEV;
 
index 99d820a..147f6c7 100644 (file)
@@ -1029,6 +1029,9 @@ void __init acpi_early_init(void)
 
        acpi_permanent_mmap = true;
 
+       /* Initialize debug output. Linux does not use ACPICA defaults */
+       acpi_dbg_level = ACPI_LV_INFO | ACPI_LV_REPAIR;
+
 #ifdef CONFIG_X86
        /*
         * If the machine falls into the DMI check table,
@@ -1054,18 +1057,6 @@ void __init acpi_early_init(void)
                goto error0;
        }
 
-       /*
-        * ACPI 2.0 requires the EC driver to be loaded and work before
-        * the EC device is found in the namespace (i.e. before
-        * acpi_load_tables() is called).
-        *
-        * This is accomplished by looking for the ECDT table, and getting
-        * the EC parameters out of that.
-        *
-        * Ignore the result. Not having an ECDT is not fatal.
-        */
-       status = acpi_ec_ecdt_probe();
-
 #ifdef CONFIG_X86
        if (!acpi_ioapic) {
                /* compatible (0) means level (3) */
@@ -1142,6 +1133,18 @@ static int __init acpi_bus_init(void)
                goto error1;
        }
 
+       /*
+        * ACPI 2.0 requires the EC driver to be loaded and work before the EC
+        * device is found in the namespace.
+        *
+        * This is accomplished by looking for the ECDT table and getting the EC
+        * parameters out of that.
+        *
+        * Do that before calling acpi_initialize_objects() which may trigger EC
+        * address space accesses.
+        */
+       acpi_ec_ecdt_probe();
+
        status = acpi_enable_subsystem(ACPI_NO_ACPI_ENABLE);
        if (ACPI_FAILURE(status)) {
                printk(KERN_ERR PREFIX
index 7e6952e..6a9e1fb 100644 (file)
@@ -81,7 +81,11 @@ void acpi_debugfs_init(void);
 #else
 static inline void acpi_debugfs_init(void) { return; }
 #endif
+#ifdef CONFIG_PCI
 void acpi_lpss_init(void);
+#else
+static inline void acpi_lpss_init(void) {}
+#endif
 
 void acpi_apd_init(void);
 
index 011d3db..e18ade5 100644 (file)
@@ -26,7 +26,6 @@
 #include <acpi/nfit.h>
 #include "intel.h"
 #include "nfit.h"
-#include "intel.h"
 
 /*
  * For readq() and writeq() on 32-bit builds, the hi-lo, lo-hi order is
@@ -78,12 +77,6 @@ const guid_t *to_nfit_uuid(enum nfit_uuids id)
 }
 EXPORT_SYMBOL(to_nfit_uuid);
 
-static struct acpi_nfit_desc *to_acpi_nfit_desc(
-               struct nvdimm_bus_descriptor *nd_desc)
-{
-       return container_of(nd_desc, struct acpi_nfit_desc, nd_desc);
-}
-
 static struct acpi_device *to_acpi_dev(struct acpi_nfit_desc *acpi_desc)
 {
        struct nvdimm_bus_descriptor *nd_desc = &acpi_desc->nd_desc;
@@ -416,10 +409,36 @@ static bool payload_dumpable(struct nvdimm *nvdimm, unsigned int func)
        return true;
 }
 
+static int cmd_to_func(struct nfit_mem *nfit_mem, unsigned int cmd,
+               struct nd_cmd_pkg *call_pkg)
+{
+       if (call_pkg) {
+               int i;
+
+               if (nfit_mem->family != call_pkg->nd_family)
+                       return -ENOTTY;
+
+               for (i = 0; i < ARRAY_SIZE(call_pkg->nd_reserved2); i++)
+                       if (call_pkg->nd_reserved2[i])
+                               return -EINVAL;
+               return call_pkg->nd_command;
+       }
+
+       /* Linux ND commands == NVDIMM_FAMILY_INTEL function numbers */
+       if (nfit_mem->family == NVDIMM_FAMILY_INTEL)
+               return cmd;
+
+       /*
+        * Force function number validation to fail since 0 is never
+        * published as a valid function in dsm_mask.
+        */
+       return 0;
+}
+
 int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
                unsigned int cmd, void *buf, unsigned int buf_len, int *cmd_rc)
 {
-       struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
+       struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
        struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
        union acpi_object in_obj, in_buf, *out_obj;
        const struct nd_cmd_desc *desc = NULL;
@@ -429,30 +448,23 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
        unsigned long cmd_mask, dsm_mask;
        u32 offset, fw_status = 0;
        acpi_handle handle;
-       unsigned int func;
        const guid_t *guid;
-       int rc, i;
+       int func, rc, i;
 
        if (cmd_rc)
                *cmd_rc = -EINVAL;
-       func = cmd;
-       if (cmd == ND_CMD_CALL) {
-               call_pkg = buf;
-               func = call_pkg->nd_command;
-
-               for (i = 0; i < ARRAY_SIZE(call_pkg->nd_reserved2); i++)
-                       if (call_pkg->nd_reserved2[i])
-                               return -EINVAL;
-       }
 
        if (nvdimm) {
                struct acpi_device *adev = nfit_mem->adev;
 
                if (!adev)
                        return -ENOTTY;
-               if (call_pkg && nfit_mem->family != call_pkg->nd_family)
-                       return -ENOTTY;
 
+               if (cmd == ND_CMD_CALL)
+                       call_pkg = buf;
+               func = cmd_to_func(nfit_mem, cmd, call_pkg);
+               if (func < 0)
+                       return func;
                dimm_name = nvdimm_name(nvdimm);
                cmd_name = nvdimm_cmd_name(cmd);
                cmd_mask = nvdimm_cmd_mask(nvdimm);
@@ -463,6 +475,7 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
        } else {
                struct acpi_device *adev = to_acpi_dev(acpi_desc);
 
+               func = cmd;
                cmd_name = nvdimm_bus_cmd_name(cmd);
                cmd_mask = nd_desc->cmd_mask;
                dsm_mask = cmd_mask;
@@ -477,7 +490,13 @@ int acpi_nfit_ctl(struct nvdimm_bus_descriptor *nd_desc, struct nvdimm *nvdimm,
        if (!desc || (cmd && (desc->out_num + desc->in_num == 0)))
                return -ENOTTY;
 
-       if (!test_bit(cmd, &cmd_mask) || !test_bit(func, &dsm_mask))
+       /*
+        * Check for a valid command.  For ND_CMD_CALL, we also have to
+        * make sure that the DSM function is supported.
+        */
+       if (cmd == ND_CMD_CALL && !test_bit(func, &dsm_mask))
+               return -ENOTTY;
+       else if (!test_bit(cmd, &cmd_mask))
                return -ENOTTY;
 
        in_obj.type = ACPI_TYPE_PACKAGE;
@@ -721,6 +740,7 @@ int nfit_get_smbios_id(u32 device_handle, u16 *flags)
        struct acpi_nfit_memory_map *memdev;
        struct acpi_nfit_desc *acpi_desc;
        struct nfit_mem *nfit_mem;
+       u16 physical_id;
 
        mutex_lock(&acpi_desc_lock);
        list_for_each_entry(acpi_desc, &acpi_descs, list) {
@@ -728,10 +748,11 @@ int nfit_get_smbios_id(u32 device_handle, u16 *flags)
                list_for_each_entry(nfit_mem, &acpi_desc->dimms, list) {
                        memdev = __to_nfit_memdev(nfit_mem);
                        if (memdev->device_handle == device_handle) {
+                               *flags = memdev->flags;
+                               physical_id = memdev->physical_id;
                                mutex_unlock(&acpi_desc->init_mutex);
                                mutex_unlock(&acpi_desc_lock);
-                               *flags = memdev->flags;
-                               return memdev->physical_id;
+                               return physical_id;
                        }
                }
                mutex_unlock(&acpi_desc->init_mutex);
@@ -1872,6 +1893,13 @@ static int acpi_nfit_add_dimm(struct acpi_nfit_desc *acpi_desc,
                return 0;
        }
 
+       /*
+        * Function 0 is the command interrogation function, don't
+        * export it to potential userspace use, and enable it to be
+        * used as an error value in acpi_nfit_ctl().
+        */
+       dsm_mask &= ~1UL;
+
        guid = to_nfit_uuid(nfit_mem->family);
        for_each_set_bit(i, &dsm_mask, BITS_PER_LONG)
                if (acpi_check_dsm(adev_dimm->handle, guid,
@@ -2047,11 +2075,6 @@ static int acpi_nfit_register_dimms(struct acpi_nfit_desc *acpi_desc)
                if (!nvdimm)
                        continue;
 
-               rc = nvdimm_security_setup_events(nvdimm);
-               if (rc < 0)
-                       dev_warn(acpi_desc->dev,
-                               "security event setup failed: %d\n", rc);
-
                nfit_kernfs = sysfs_get_dirent(nvdimm_kobj(nvdimm)->sd, "nfit");
                if (nfit_kernfs)
                        nfit_mem->flags_attr = sysfs_get_dirent(nfit_kernfs,
@@ -2231,7 +2254,6 @@ static int acpi_nfit_init_interleave_set(struct acpi_nfit_desc *acpi_desc,
        nd_set = devm_kzalloc(dev, sizeof(*nd_set), GFP_KERNEL);
        if (!nd_set)
                return -ENOMEM;
-       ndr_desc->nd_set = nd_set;
        guid_copy(&nd_set->type_guid, (guid_t *) spa->range_guid);
 
        info = devm_kzalloc(dev, sizeof_nfit_set_info(nr), GFP_KERNEL);
@@ -3367,7 +3389,7 @@ EXPORT_SYMBOL_GPL(acpi_nfit_init);
 
 static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
 {
-       struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
+       struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
        struct device *dev = acpi_desc->dev;
 
        /* Bounce the device lock to flush acpi_nfit_add / acpi_nfit_notify */
@@ -3384,7 +3406,7 @@ static int acpi_nfit_flush_probe(struct nvdimm_bus_descriptor *nd_desc)
 static int __acpi_nfit_clear_to_send(struct nvdimm_bus_descriptor *nd_desc,
                struct nvdimm *nvdimm, unsigned int cmd)
 {
-       struct acpi_nfit_desc *acpi_desc = to_acpi_nfit_desc(nd_desc);
+       struct acpi_nfit_desc *acpi_desc = to_acpi_desc(nd_desc);
 
        if (nvdimm)
                return 0;
index 850b292..f70de71 100644 (file)
@@ -146,7 +146,7 @@ static int intel_security_change_key(struct nvdimm *nvdimm,
 
 static void nvdimm_invalidate_cache(void);
 
-static int intel_security_unlock(struct nvdimm *nvdimm,
+static int __maybe_unused intel_security_unlock(struct nvdimm *nvdimm,
                const struct nvdimm_key_data *key_data)
 {
        struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
@@ -227,7 +227,7 @@ static int intel_security_disable(struct nvdimm *nvdimm,
        return 0;
 }
 
-static int intel_security_erase(struct nvdimm *nvdimm,
+static int __maybe_unused intel_security_erase(struct nvdimm *nvdimm,
                const struct nvdimm_key_data *key,
                enum nvdimm_passphrase_type ptype)
 {
@@ -276,7 +276,7 @@ static int intel_security_erase(struct nvdimm *nvdimm,
        return 0;
 }
 
-static int intel_security_query_overwrite(struct nvdimm *nvdimm)
+static int __maybe_unused intel_security_query_overwrite(struct nvdimm *nvdimm)
 {
        int rc;
        struct nfit_mem *nfit_mem = nvdimm_provider_data(nvdimm);
@@ -313,7 +313,7 @@ static int intel_security_query_overwrite(struct nvdimm *nvdimm)
        return 0;
 }
 
-static int intel_security_overwrite(struct nvdimm *nvdimm,
+static int __maybe_unused intel_security_overwrite(struct nvdimm *nvdimm,
                const struct nvdimm_key_data *nkey)
 {
        int rc;
index 2746994..7bbbf82 100644 (file)
@@ -146,9 +146,9 @@ acpi_table_print_srat_entry(struct acpi_subtable_header *header)
                {
                        struct acpi_srat_mem_affinity *p =
                            (struct acpi_srat_mem_affinity *)header;
-                       pr_debug("SRAT Memory (0x%lx length 0x%lx) in proximity domain %d %s%s%s\n",
-                                (unsigned long)p->base_address,
-                                (unsigned long)p->length,
+                       pr_debug("SRAT Memory (0x%llx length 0x%llx) in proximity domain %d %s%s%s\n",
+                                (unsigned long long)p->base_address,
+                                (unsigned long long)p->length,
                                 p->proximity_domain,
                                 (p->flags & ACPI_SRAT_MEM_ENABLED) ?
                                 "enabled" : "disabled",
index 2579675..e7c0006 100644 (file)
 #define GPI1_LDO_ON            (3 << 0)
 #define GPI1_LDO_OFF           (4 << 0)
 
-#define AXP288_ADC_TS_PIN_GPADC        0xf2
-#define AXP288_ADC_TS_PIN_ON   0xf3
+#define AXP288_ADC_TS_CURRENT_ON_OFF_MASK              GENMASK(1, 0)
+#define AXP288_ADC_TS_CURRENT_OFF                      (0 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING         (1 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_ONDEMAND              (2 << 0)
+#define AXP288_ADC_TS_CURRENT_ON                       (3 << 0)
 
 static struct pmic_table power_table[] = {
        {
@@ -212,22 +215,44 @@ out:
  */
 static int intel_xpower_pmic_get_raw_temp(struct regmap *regmap, int reg)
 {
+       int ret, adc_ts_pin_ctrl;
        u8 buf[2];
-       int ret;
 
-       ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL,
-                          AXP288_ADC_TS_PIN_GPADC);
+       /*
+        * The current-source used for the battery temp-sensor (TS) is shared
+        * with the GPADC. For proper fuel-gauge and charger operation the TS
+        * current-source needs to be permanently on. But to read the GPADC we
+        * need to temporary switch the TS current-source to ondemand, so that
+        * the GPADC can use it, otherwise we will always read an all 0 value.
+        *
+        * Note that the switching from on to on-ondemand is not necessary
+        * when the TS current-source is off (this happens on devices which
+        * do not use the TS-pin).
+        */
+       ret = regmap_read(regmap, AXP288_ADC_TS_PIN_CTRL, &adc_ts_pin_ctrl);
        if (ret)
                return ret;
 
-       /* After switching to the GPADC pin give things some time to settle */
-       usleep_range(6000, 10000);
+       if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) {
+               ret = regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL,
+                                        AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+                                        AXP288_ADC_TS_CURRENT_ON_ONDEMAND);
+               if (ret)
+                       return ret;
+
+               /* Wait a bit after switching the current-source */
+               usleep_range(6000, 10000);
+       }
 
        ret = regmap_bulk_read(regmap, AXP288_GP_ADC_H, buf, 2);
        if (ret == 0)
                ret = (buf[0] << 4) + ((buf[1] >> 4) & 0x0f);
 
-       regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON);
+       if (adc_ts_pin_ctrl & AXP288_ADC_TS_CURRENT_ON_OFF_MASK) {
+               regmap_update_bits(regmap, AXP288_ADC_TS_PIN_CTRL,
+                                  AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+                                  AXP288_ADC_TS_CURRENT_ON);
+       }
 
        return ret;
 }
index 1b475bc..665e93c 100644 (file)
@@ -131,6 +131,23 @@ void acpi_power_resources_list_free(struct list_head *list)
        }
 }
 
+static bool acpi_power_resource_is_dup(union acpi_object *package,
+                                      unsigned int start, unsigned int i)
+{
+       acpi_handle rhandle, dup;
+       unsigned int j;
+
+       /* The caller is expected to check the package element types */
+       rhandle = package->package.elements[i].reference.handle;
+       for (j = start; j < i; j++) {
+               dup = package->package.elements[j].reference.handle;
+               if (dup == rhandle)
+                       return true;
+       }
+
+       return false;
+}
+
 int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
                                 struct list_head *list)
 {
@@ -150,6 +167,11 @@ int acpi_extract_power_resources(union acpi_object *package, unsigned int start,
                        err = -ENODEV;
                        break;
                }
+
+               /* Some ACPI tables contain duplicate power resource references */
+               if (acpi_power_resource_is_dup(package, start, i))
+                       continue;
+
                err = acpi_add_power_resource(rhandle);
                if (err)
                        break;
index cdfc876..4d2b2ad 100644 (file)
@@ -5854,9 +5854,10 @@ static int __init init_binder_device(const char *name)
 static int __init binder_init(void)
 {
        int ret;
-       char *device_name, *device_names, *device_tmp;
+       char *device_name, *device_tmp;
        struct binder_device *device;
        struct hlist_node *tmp;
+       char *device_names = NULL;
 
        ret = binder_alloc_shrinker_init();
        if (ret)
@@ -5898,23 +5899,29 @@ static int __init binder_init(void)
                                    &transaction_log_fops);
        }
 
-       /*
-        * Copy the module_parameter string, because we don't want to
-        * tokenize it in-place.
-        */
-       device_names = kstrdup(binder_devices_param, GFP_KERNEL);
-       if (!device_names) {
-               ret = -ENOMEM;
-               goto err_alloc_device_names_failed;
-       }
+       if (strcmp(binder_devices_param, "") != 0) {
+               /*
+               * Copy the module_parameter string, because we don't want to
+               * tokenize it in-place.
+                */
+               device_names = kstrdup(binder_devices_param, GFP_KERNEL);
+               if (!device_names) {
+                       ret = -ENOMEM;
+                       goto err_alloc_device_names_failed;
+               }
 
-       device_tmp = device_names;
-       while ((device_name = strsep(&device_tmp, ","))) {
-               ret = init_binder_device(device_name);
-               if (ret)
-                       goto err_init_binder_device_failed;
+               device_tmp = device_names;
+               while ((device_name = strsep(&device_tmp, ","))) {
+                       ret = init_binder_device(device_name);
+                       if (ret)
+                               goto err_init_binder_device_failed;
+               }
        }
 
+       ret = init_binderfs();
+       if (ret)
+               goto err_init_binder_device_failed;
+
        return ret;
 
 err_init_binder_device_failed:
index 7fb97f5..045b3e4 100644 (file)
@@ -46,4 +46,13 @@ static inline bool is_binderfs_device(const struct inode *inode)
 }
 #endif
 
+#ifdef CONFIG_ANDROID_BINDERFS
+extern int __init init_binderfs(void);
+#else
+static inline int __init init_binderfs(void)
+{
+       return 0;
+}
+#endif
+
 #endif /* _LINUX_BINDER_INTERNAL_H */
index 7496b10..e773f45 100644 (file)
@@ -11,6 +11,7 @@
 #include <linux/kdev_t.h>
 #include <linux/kernel.h>
 #include <linux/list.h>
+#include <linux/namei.h>
 #include <linux/magic.h>
 #include <linux/major.h>
 #include <linux/miscdevice.h>
@@ -20,6 +21,7 @@
 #include <linux/parser.h>
 #include <linux/radix-tree.h>
 #include <linux/sched.h>
+#include <linux/seq_file.h>
 #include <linux/slab.h>
 #include <linux/spinlock_types.h>
 #include <linux/stddef.h>
@@ -30,7 +32,7 @@
 #include <linux/xarray.h>
 #include <uapi/asm-generic/errno-base.h>
 #include <uapi/linux/android/binder.h>
-#include <uapi/linux/android/binder_ctl.h>
+#include <uapi/linux/android/binderfs.h>
 
 #include "binder_internal.h"
 
 #define INODE_OFFSET 3
 #define INTSTRLEN 21
 #define BINDERFS_MAX_MINOR (1U << MINORBITS)
-
-static struct vfsmount *binderfs_mnt;
+/* Ensure that the initial ipc namespace always has devices available. */
+#define BINDERFS_MAX_MINOR_CAPPED (BINDERFS_MAX_MINOR - 4)
 
 static dev_t binderfs_dev;
 static DEFINE_MUTEX(binderfs_minors_mutex);
 static DEFINE_IDA(binderfs_minors);
 
+/**
+ * binderfs_mount_opts - mount options for binderfs
+ * @max: maximum number of allocatable binderfs binder devices
+ */
+struct binderfs_mount_opts {
+       int max;
+};
+
+enum {
+       Opt_max,
+       Opt_err
+};
+
+static const match_table_t tokens = {
+       { Opt_max, "max=%d" },
+       { Opt_err, NULL     }
+};
+
 /**
  * binderfs_info - information about a binderfs mount
  * @ipc_ns:         The ipc namespace the binderfs mount belongs to.
@@ -55,13 +75,16 @@ static DEFINE_IDA(binderfs_minors);
  *                  created.
  * @root_gid:       gid that needs to be used when a new binder device is
  *                  created.
+ * @mount_opts:     The mount options in use.
+ * @device_count:   The current number of allocated binder devices.
  */
 struct binderfs_info {
        struct ipc_namespace *ipc_ns;
        struct dentry *control_dentry;
        kuid_t root_uid;
        kgid_t root_gid;
-
+       struct binderfs_mount_opts mount_opts;
+       int device_count;
 };
 
 static inline struct binderfs_info *BINDERFS_I(const struct inode *inode)
@@ -84,7 +107,7 @@ bool is_binderfs_device(const struct inode *inode)
  * @userp:     buffer to copy information about new device for userspace to
  * @req:       struct binderfs_device as copied from userspace
  *
- * This function allocated a new binder_device and reserves a new minor
+ * This function allocates a new binder_device and reserves a new minor
  * number for it.
  * Minor numbers are limited and tracked globally in binderfs_minors. The
  * function will stash a struct binder_device for the specific binder
@@ -100,20 +123,34 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
                                         struct binderfs_device *req)
 {
        int minor, ret;
-       struct dentry *dentry, *dup, *root;
+       struct dentry *dentry, *root;
        struct binder_device *device;
-       size_t name_len = BINDERFS_MAX_NAME + 1;
        char *name = NULL;
+       size_t name_len;
        struct inode *inode = NULL;
        struct super_block *sb = ref_inode->i_sb;
        struct binderfs_info *info = sb->s_fs_info;
+#if defined(CONFIG_IPC_NS)
+       bool use_reserve = (info->ipc_ns == &init_ipc_ns);
+#else
+       bool use_reserve = true;
+#endif
 
        /* Reserve new minor number for the new device. */
        mutex_lock(&binderfs_minors_mutex);
-       minor = ida_alloc_max(&binderfs_minors, BINDERFS_MAX_MINOR, GFP_KERNEL);
-       mutex_unlock(&binderfs_minors_mutex);
-       if (minor < 0)
+       if (++info->device_count <= info->mount_opts.max)
+               minor = ida_alloc_max(&binderfs_minors,
+                                     use_reserve ? BINDERFS_MAX_MINOR :
+                                                   BINDERFS_MAX_MINOR_CAPPED,
+                                     GFP_KERNEL);
+       else
+               minor = -ENOSPC;
+       if (minor < 0) {
+               --info->device_count;
+               mutex_unlock(&binderfs_minors_mutex);
                return minor;
+       }
+       mutex_unlock(&binderfs_minors_mutex);
 
        ret = -ENOMEM;
        device = kzalloc(sizeof(*device), GFP_KERNEL);
@@ -132,12 +169,13 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
        inode->i_uid = info->root_uid;
        inode->i_gid = info->root_gid;
 
-       name = kmalloc(name_len, GFP_KERNEL);
+       req->name[BINDERFS_MAX_NAME] = '\0'; /* NUL-terminate */
+       name_len = strlen(req->name);
+       /* Make sure to include terminating NUL byte */
+       name = kmemdup(req->name, name_len + 1, GFP_KERNEL);
        if (!name)
                goto err;
 
-       strscpy(name, req->name, name_len);
-
        device->binderfs_inode = inode;
        device->context.binder_context_mgr_uid = INVALID_UID;
        device->context.name = name;
@@ -156,28 +194,25 @@ static int binderfs_binder_device_create(struct inode *ref_inode,
 
        root = sb->s_root;
        inode_lock(d_inode(root));
-       dentry = d_alloc_name(root, name);
-       if (!dentry) {
+
+       /* look it up */
+       dentry = lookup_one_len(name, root, name_len);
+       if (IS_ERR(dentry)) {
                inode_unlock(d_inode(root));
-               ret = -ENOMEM;
+               ret = PTR_ERR(dentry);
                goto err;
        }
 
-       /* Verify that the name userspace gave us is not already in use. */
-       dup = d_lookup(root, &dentry->d_name);
-       if (dup) {
-               if (d_really_is_positive(dup)) {
-                       dput(dup);
-                       dput(dentry);
-                       inode_unlock(d_inode(root));
-                       ret = -EEXIST;
-                       goto err;
-               }
-               dput(dup);
+       if (d_really_is_positive(dentry)) {
+               /* already exists */
+               dput(dentry);
+               inode_unlock(d_inode(root));
+               ret = -EEXIST;
+               goto err;
        }
 
        inode->i_private = device;
-       d_add(dentry, inode);
+       d_instantiate(dentry, inode);
        fsnotify_create(root->d_inode, dentry);
        inode_unlock(d_inode(root));
 
@@ -187,6 +222,7 @@ err:
        kfree(name);
        kfree(device);
        mutex_lock(&binderfs_minors_mutex);
+       --info->device_count;
        ida_free(&binderfs_minors, minor);
        mutex_unlock(&binderfs_minors_mutex);
        iput(inode);
@@ -232,6 +268,7 @@ static long binder_ctl_ioctl(struct file *file, unsigned int cmd,
 static void binderfs_evict_inode(struct inode *inode)
 {
        struct binder_device *device = inode->i_private;
+       struct binderfs_info *info = BINDERFS_I(inode);
 
        clear_inode(inode);
 
@@ -239,6 +276,7 @@ static void binderfs_evict_inode(struct inode *inode)
                return;
 
        mutex_lock(&binderfs_minors_mutex);
+       --info->device_count;
        ida_free(&binderfs_minors, device->miscdev.minor);
        mutex_unlock(&binderfs_minors_mutex);
 
@@ -246,43 +284,87 @@ static void binderfs_evict_inode(struct inode *inode)
        kfree(device);
 }
 
+/**
+ * binderfs_parse_mount_opts - parse binderfs mount options
+ * @data: options to set (can be NULL in which case defaults are used)
+ */
+static int binderfs_parse_mount_opts(char *data,
+                                    struct binderfs_mount_opts *opts)
+{
+       char *p;
+       opts->max = BINDERFS_MAX_MINOR;
+
+       while ((p = strsep(&data, ",")) != NULL) {
+               substring_t args[MAX_OPT_ARGS];
+               int token;
+               int max_devices;
+
+               if (!*p)
+                       continue;
+
+               token = match_token(p, tokens, args);
+               switch (token) {
+               case Opt_max:
+                       if (match_int(&args[0], &max_devices) ||
+                           (max_devices < 0 ||
+                            (max_devices > BINDERFS_MAX_MINOR)))
+                               return -EINVAL;
+
+                       opts->max = max_devices;
+                       break;
+               default:
+                       pr_err("Invalid mount options\n");
+                       return -EINVAL;
+               }
+       }
+
+       return 0;
+}
+
+static int binderfs_remount(struct super_block *sb, int *flags, char *data)
+{
+       struct binderfs_info *info = sb->s_fs_info;
+       return binderfs_parse_mount_opts(data, &info->mount_opts);
+}
+
+static int binderfs_show_mount_opts(struct seq_file *seq, struct dentry *root)
+{
+       struct binderfs_info *info;
+
+       info = root->d_sb->s_fs_info;
+       if (info->mount_opts.max <= BINDERFS_MAX_MINOR)
+               seq_printf(seq, ",max=%d", info->mount_opts.max);
+
+       return 0;
+}
+
 static const struct super_operations binderfs_super_ops = {
-       .statfs = simple_statfs,
-       .evict_inode = binderfs_evict_inode,
+       .evict_inode    = binderfs_evict_inode,
+       .remount_fs     = binderfs_remount,
+       .show_options   = binderfs_show_mount_opts,
+       .statfs         = simple_statfs,
 };
 
+static inline bool is_binderfs_control_device(const struct dentry *dentry)
+{
+       struct binderfs_info *info = dentry->d_sb->s_fs_info;
+       return info->control_dentry == dentry;
+}
+
 static int binderfs_rename(struct inode *old_dir, struct dentry *old_dentry,
                           struct inode *new_dir, struct dentry *new_dentry,
                           unsigned int flags)
 {
-       struct inode *inode = d_inode(old_dentry);
-
-       /* binderfs doesn't support directories. */
-       if (d_is_dir(old_dentry))
+       if (is_binderfs_control_device(old_dentry) ||
+           is_binderfs_control_device(new_dentry))
                return -EPERM;
 
-       if (flags & ~RENAME_NOREPLACE)
-               return -EINVAL;
-
-       if (!simple_empty(new_dentry))
-               return -ENOTEMPTY;
-
-       if (d_really_is_positive(new_dentry))
-               simple_unlink(new_dir, new_dentry);
-
-       old_dir->i_ctime = old_dir->i_mtime = new_dir->i_ctime =
-               new_dir->i_mtime = inode->i_ctime = current_time(old_dir);
-
-       return 0;
+       return simple_rename(old_dir, old_dentry, new_dir, new_dentry, flags);
 }
 
 static int binderfs_unlink(struct inode *dir, struct dentry *dentry)
 {
-       /*
-        * The control dentry is only ever touched during mount so checking it
-        * here should not require us to take lock.
-        */
-       if (BINDERFS_I(dir)->control_dentry == dentry)
+       if (is_binderfs_control_device(dentry))
                return -EPERM;
 
        return simple_unlink(dir, dentry);
@@ -313,13 +395,16 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
        struct inode *inode = NULL;
        struct dentry *root = sb->s_root;
        struct binderfs_info *info = sb->s_fs_info;
+#if defined(CONFIG_IPC_NS)
+       bool use_reserve = (info->ipc_ns == &init_ipc_ns);
+#else
+       bool use_reserve = true;
+#endif
 
        device = kzalloc(sizeof(*device), GFP_KERNEL);
        if (!device)
                return -ENOMEM;
 
-       inode_lock(d_inode(root));
-
        /* If we have already created a binder-control node, return. */
        if (info->control_dentry) {
                ret = 0;
@@ -333,7 +418,10 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
 
        /* Reserve a new minor number for the new device. */
        mutex_lock(&binderfs_minors_mutex);
-       minor = ida_alloc_max(&binderfs_minors, BINDERFS_MAX_MINOR, GFP_KERNEL);
+       minor = ida_alloc_max(&binderfs_minors,
+                             use_reserve ? BINDERFS_MAX_MINOR :
+                                           BINDERFS_MAX_MINOR_CAPPED,
+                             GFP_KERNEL);
        mutex_unlock(&binderfs_minors_mutex);
        if (minor < 0) {
                ret = minor;
@@ -358,12 +446,10 @@ static int binderfs_binder_ctl_create(struct super_block *sb)
        inode->i_private = device;
        info->control_dentry = dentry;
        d_add(dentry, inode);
-       inode_unlock(d_inode(root));
 
        return 0;
 
 out:
-       inode_unlock(d_inode(root));
        kfree(device);
        iput(inode);
 
@@ -378,12 +464,9 @@ static const struct inode_operations binderfs_dir_inode_operations = {
 
 static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
 {
+       int ret;
        struct binderfs_info *info;
-       int ret = -ENOMEM;
        struct inode *inode = NULL;
-       struct ipc_namespace *ipc_ns = sb->s_fs_info;
-
-       get_ipc_ns(ipc_ns);
 
        sb->s_blocksize = PAGE_SIZE;
        sb->s_blocksize_bits = PAGE_SHIFT;
@@ -405,11 +488,17 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
        sb->s_op = &binderfs_super_ops;
        sb->s_time_gran = 1;
 
-       info = kzalloc(sizeof(struct binderfs_info), GFP_KERNEL);
-       if (!info)
-               goto err_without_dentry;
+       sb->s_fs_info = kzalloc(sizeof(struct binderfs_info), GFP_KERNEL);
+       if (!sb->s_fs_info)
+               return -ENOMEM;
+       info = sb->s_fs_info;
+
+       info->ipc_ns = get_ipc_ns(current->nsproxy->ipc_ns);
+
+       ret = binderfs_parse_mount_opts(data, &info->mount_opts);
+       if (ret)
+               return ret;
 
-       info->ipc_ns = ipc_ns;
        info->root_gid = make_kgid(sb->s_user_ns, 0);
        if (!gid_valid(info->root_gid))
                info->root_gid = GLOBAL_ROOT_GID;
@@ -417,11 +506,9 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
        if (!uid_valid(info->root_uid))
                info->root_uid = GLOBAL_ROOT_UID;
 
-       sb->s_fs_info = info;
-
        inode = new_inode(sb);
        if (!inode)
-               goto err_without_dentry;
+               return -ENOMEM;
 
        inode->i_ino = FIRST_INODE;
        inode->i_fop = &simple_dir_operations;
@@ -432,79 +519,28 @@ static int binderfs_fill_super(struct super_block *sb, void *data, int silent)
 
        sb->s_root = d_make_root(inode);
        if (!sb->s_root)
-               goto err_without_dentry;
-
-       ret = binderfs_binder_ctl_create(sb);
-       if (ret)
-               goto err_with_dentry;
-
-       return 0;
-
-err_with_dentry:
-       dput(sb->s_root);
-       sb->s_root = NULL;
-
-err_without_dentry:
-       put_ipc_ns(ipc_ns);
-       iput(inode);
-       kfree(info);
-
-       return ret;
-}
-
-static int binderfs_test_super(struct super_block *sb, void *data)
-{
-       struct binderfs_info *info = sb->s_fs_info;
-
-       if (info)
-               return info->ipc_ns == data;
-
-       return 0;
-}
+               return -ENOMEM;
 
-static int binderfs_set_super(struct super_block *sb, void *data)
-{
-       sb->s_fs_info = data;
-       return set_anon_super(sb, NULL);
+       return binderfs_binder_ctl_create(sb);
 }
 
 static struct dentry *binderfs_mount(struct file_system_type *fs_type,
                                     int flags, const char *dev_name,
                                     void *data)
 {
-       struct super_block *sb;
-       struct ipc_namespace *ipc_ns = current->nsproxy->ipc_ns;
-
-       if (!ns_capable(ipc_ns->user_ns, CAP_SYS_ADMIN))
-               return ERR_PTR(-EPERM);
-
-       sb = sget_userns(fs_type, binderfs_test_super, binderfs_set_super,
-                        flags, ipc_ns->user_ns, ipc_ns);
-       if (IS_ERR(sb))
-               return ERR_CAST(sb);
-
-       if (!sb->s_root) {
-               int ret = binderfs_fill_super(sb, data, flags & SB_SILENT ? 1 : 0);
-               if (ret) {
-                       deactivate_locked_super(sb);
-                       return ERR_PTR(ret);
-               }
-
-               sb->s_flags |= SB_ACTIVE;
-       }
-
-       return dget(sb->s_root);
+       return mount_nodev(fs_type, flags, data, binderfs_fill_super);
 }
 
 static void binderfs_kill_super(struct super_block *sb)
 {
        struct binderfs_info *info = sb->s_fs_info;
 
+       kill_litter_super(sb);
+
        if (info && info->ipc_ns)
                put_ipc_ns(info->ipc_ns);
 
        kfree(info);
-       kill_litter_super(sb);
 }
 
 static struct file_system_type binder_fs_type = {
@@ -514,7 +550,7 @@ static struct file_system_type binder_fs_type = {
        .fs_flags       = FS_USERNS_MOUNT,
 };
 
-static int __init init_binderfs(void)
+int __init init_binderfs(void)
 {
        int ret;
 
@@ -530,15 +566,5 @@ static int __init init_binderfs(void)
                return ret;
        }
 
-       binderfs_mnt = kern_mount(&binder_fs_type);
-       if (IS_ERR(binderfs_mnt)) {
-               ret = PTR_ERR(binderfs_mnt);
-               binderfs_mnt = NULL;
-               unregister_filesystem(&binder_fs_type);
-               unregister_chrdev_region(binderfs_dev, BINDERFS_MAX_MINOR);
-       }
-
        return ret;
 }
-
-device_initcall(init_binderfs);
index 4ca7a6b..8218db1 100644 (file)
@@ -1091,7 +1091,7 @@ comment "Generic fallback / legacy drivers"
 
 config PATA_ACPI
        tristate "ACPI firmware driver for PATA"
-       depends on ATA_ACPI && ATA_BMDMA
+       depends on ATA_ACPI && ATA_BMDMA && PCI
        help
          This option enables an ACPI method driver which drives
          motherboard PATA controller interfaces through the ACPI
index ef356e7..8810475 100644 (file)
@@ -254,6 +254,8 @@ enum {
        AHCI_HFLAG_IS_MOBILE            = (1 << 25), /* mobile chipset, use
                                                        SATA_MOBILE_LPM_POLICY
                                                        as default lpm_policy */
+       AHCI_HFLAG_SUSPEND_PHYS         = (1 << 26), /* handle PHYs during
+                                                       suspend/resume */
 
        /* ap->flags bits */
 
index f9cb51b..d4bba3a 100644 (file)
 #define AHCI_WINDOW_BASE(win)  (0x64 + ((win) << 4))
 #define AHCI_WINDOW_SIZE(win)  (0x68 + ((win) << 4))
 
+struct ahci_mvebu_plat_data {
+       int (*plat_config)(struct ahci_host_priv *hpriv);
+       unsigned int flags;
+};
+
 static void ahci_mvebu_mbus_config(struct ahci_host_priv *hpriv,
                                   const struct mbus_dram_target_info *dram)
 {
@@ -62,6 +67,35 @@ static void ahci_mvebu_regret_option(struct ahci_host_priv *hpriv)
        writel(0x80, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA);
 }
 
+static int ahci_mvebu_armada_380_config(struct ahci_host_priv *hpriv)
+{
+       const struct mbus_dram_target_info *dram;
+       int rc = 0;
+
+       dram = mv_mbus_dram_info();
+       if (dram)
+               ahci_mvebu_mbus_config(hpriv, dram);
+       else
+               rc = -ENODEV;
+
+       ahci_mvebu_regret_option(hpriv);
+
+       return rc;
+}
+
+static int ahci_mvebu_armada_3700_config(struct ahci_host_priv *hpriv)
+{
+       u32 reg;
+
+       writel(0, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_ADDR);
+
+       reg = readl(hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA);
+       reg |= BIT(6);
+       writel(reg, hpriv->mmio + AHCI_VENDOR_SPECIFIC_0_DATA);
+
+       return 0;
+}
+
 /**
  * ahci_mvebu_stop_engine
  *
@@ -126,13 +160,9 @@ static int ahci_mvebu_resume(struct platform_device *pdev)
 {
        struct ata_host *host = platform_get_drvdata(pdev);
        struct ahci_host_priv *hpriv = host->private_data;
-       const struct mbus_dram_target_info *dram;
+       const struct ahci_mvebu_plat_data *pdata = hpriv->plat_data;
 
-       dram = mv_mbus_dram_info();
-       if (dram)
-               ahci_mvebu_mbus_config(hpriv, dram);
-
-       ahci_mvebu_regret_option(hpriv);
+       pdata->plat_config(hpriv);
 
        return ahci_platform_resume_host(&pdev->dev);
 }
@@ -154,29 +184,30 @@ static struct scsi_host_template ahci_platform_sht = {
 
 static int ahci_mvebu_probe(struct platform_device *pdev)
 {
+       const struct ahci_mvebu_plat_data *pdata;
        struct ahci_host_priv *hpriv;
-       const struct mbus_dram_target_info *dram;
        int rc;
 
+       pdata = of_device_get_match_data(&pdev->dev);
+       if (!pdata)
+               return -EINVAL;
+
        hpriv = ahci_platform_get_resources(pdev, 0);
        if (IS_ERR(hpriv))
                return PTR_ERR(hpriv);
 
+       hpriv->flags |= pdata->flags;
+       hpriv->plat_data = (void *)pdata;
+
        rc = ahci_platform_enable_resources(hpriv);
        if (rc)
                return rc;
 
        hpriv->stop_engine = ahci_mvebu_stop_engine;
 
-       if (of_device_is_compatible(pdev->dev.of_node,
-                                   "marvell,armada-380-ahci")) {
-               dram = mv_mbus_dram_info();
-               if (!dram)
-                       return -ENODEV;
-
-               ahci_mvebu_mbus_config(hpriv, dram);
-               ahci_mvebu_regret_option(hpriv);
-       }
+       rc = pdata->plat_config(hpriv);
+       if (rc)
+               goto disable_resources;
 
        rc = ahci_platform_init_host(pdev, hpriv, &ahci_mvebu_port_info,
                                     &ahci_platform_sht);
@@ -190,18 +221,28 @@ disable_resources:
        return rc;
 }
 
+static const struct ahci_mvebu_plat_data ahci_mvebu_armada_380_plat_data = {
+       .plat_config = ahci_mvebu_armada_380_config,
+};
+
+static const struct ahci_mvebu_plat_data ahci_mvebu_armada_3700_plat_data = {
+       .plat_config = ahci_mvebu_armada_3700_config,
+       .flags = AHCI_HFLAG_SUSPEND_PHYS,
+};
+
 static const struct of_device_id ahci_mvebu_of_match[] = {
-       { .compatible = "marvell,armada-380-ahci", },
-       { .compatible = "marvell,armada-3700-ahci", },
+       {
+               .compatible = "marvell,armada-380-ahci",
+               .data = &ahci_mvebu_armada_380_plat_data,
+       },
+       {
+               .compatible = "marvell,armada-3700-ahci",
+               .data = &ahci_mvebu_armada_3700_plat_data,
+       },
        { },
 };
 MODULE_DEVICE_TABLE(of, ahci_mvebu_of_match);
 
-/*
- * We currently don't provide power management related operations,
- * since there is no suspend/resume support at the platform level for
- * Armada 38x for the moment.
- */
 static struct platform_driver ahci_mvebu_driver = {
        .probe = ahci_mvebu_probe,
        .remove = ata_platform_remove_one,
index 4b900fc..81b1a33 100644 (file)
@@ -56,6 +56,12 @@ static int ahci_platform_enable_phys(struct ahci_host_priv *hpriv)
                if (rc)
                        goto disable_phys;
 
+               rc = phy_set_mode(hpriv->phys[i], PHY_MODE_SATA);
+               if (rc) {
+                       phy_exit(hpriv->phys[i]);
+                       goto disable_phys;
+               }
+
                rc = phy_power_on(hpriv->phys[i]);
                if (rc) {
                        phy_exit(hpriv->phys[i]);
@@ -738,6 +744,9 @@ int ahci_platform_suspend_host(struct device *dev)
        writel(ctl, mmio + HOST_CTL);
        readl(mmio + HOST_CTL); /* flush */
 
+       if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS)
+               ahci_platform_disable_phys(hpriv);
+
        return ata_host_suspend(host, PMSG_SUSPEND);
 }
 EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
@@ -756,6 +765,7 @@ EXPORT_SYMBOL_GPL(ahci_platform_suspend_host);
 int ahci_platform_resume_host(struct device *dev)
 {
        struct ata_host *host = dev_get_drvdata(dev);
+       struct ahci_host_priv *hpriv = host->private_data;
        int rc;
 
        if (dev->power.power_state.event == PM_EVENT_SUSPEND) {
@@ -766,6 +776,9 @@ int ahci_platform_resume_host(struct device *dev)
                ahci_init_controller(host);
        }
 
+       if (hpriv->flags & AHCI_HFLAG_SUSPEND_PHYS)
+               ahci_platform_enable_phys(hpriv);
+
        ata_host_resume(host);
 
        return 0;
index b8c3f9e..adf2878 100644 (file)
@@ -4554,6 +4554,7 @@ static const struct ata_blacklist_entry ata_device_blacklist [] = {
        { "SAMSUNG MZMPC128HBFU-000MV", "CXM14M1Q", ATA_HORKAGE_NOLPM, },
        { "SAMSUNG SSD PM830 mSATA *",  "CXM13D1Q", ATA_HORKAGE_NOLPM, },
        { "SAMSUNG MZ7TD256HAFV-000L9", NULL,       ATA_HORKAGE_NOLPM, },
+       { "SAMSUNG MZ7TE512HMHP-000L1", "EXT06L0Q", ATA_HORKAGE_NOLPM, },
 
        /* devices that don't properly handle queued TRIM commands */
        { "Micron_M500IT_*",            "MU01", ATA_HORKAGE_NO_NCQ_TRIM |
index 8cc9c42..9e7fc30 100644 (file)
@@ -915,6 +915,10 @@ static struct scsi_host_template pata_macio_sht = {
        .sg_tablesize           = MAX_DCMDS,
        /* We may not need that strict one */
        .dma_boundary           = ATA_DMA_BOUNDARY,
+       /* Not sure what the real max is but we know it's less than 64K, let's
+        * use 64K minus 256
+        */
+       .max_segment_size       = MAX_DBDMA_SEG,
        .slave_configure        = pata_macio_slave_config,
 };
 
@@ -1044,11 +1048,6 @@ static int pata_macio_common_init(struct pata_macio_priv *priv,
        /* Make sure we have sane initial timings in the cache */
        pata_macio_default_timings(priv);
 
-       /* Not sure what the real max is but we know it's less than 64K, let's
-        * use 64K minus 256
-        */
-       dma_set_max_seg_size(priv->dev, MAX_DBDMA_SEG);
-
        /* Allocate libata host for 1 port */
        memset(&pinfo, 0, sizeof(struct ata_port_info));
        pmac_macio_calc_timing_masks(priv, &pinfo);
index 4dc528b..9c1247d 100644 (file)
@@ -729,8 +729,8 @@ static int sata_fsl_port_start(struct ata_port *ap)
        if (!pp)
                return -ENOMEM;
 
-       mem = dma_zalloc_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, &mem_dma,
-                                 GFP_KERNEL);
+       mem = dma_alloc_coherent(dev, SATA_FSL_PORT_PRIV_DMA_SZ, &mem_dma,
+                                GFP_KERNEL);
        if (!mem) {
                kfree(pp);
                return -ENOMEM;
index e0bcf9b..174e84c 100644 (file)
@@ -245,8 +245,15 @@ struct inic_port_priv {
 
 static struct scsi_host_template inic_sht = {
        ATA_BASE_SHT(DRV_NAME),
-       .sg_tablesize   = LIBATA_MAX_PRD,       /* maybe it can be larger? */
-       .dma_boundary   = INIC_DMA_BOUNDARY,
+       .sg_tablesize           = LIBATA_MAX_PRD, /* maybe it can be larger? */
+
+       /*
+        * This controller is braindamaged.  dma_boundary is 0xffff like others
+        * but it will lock up the whole machine HARD if 65536 byte PRD entry
+        * is fed.  Reduce maximum segment size.
+        */
+       .dma_boundary           = INIC_DMA_BOUNDARY,
+       .max_segment_size       = 65536 - 512,
 };
 
 static const int scr_map[] = {
@@ -868,17 +875,6 @@ static int inic_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
                return rc;
        }
 
-       /*
-        * This controller is braindamaged.  dma_boundary is 0xffff
-        * like others but it will lock up the whole machine HARD if
-        * 65536 byte PRD entry is fed. Reduce maximum segment size.
-        */
-       rc = dma_set_max_seg_size(&pdev->dev, 65536 - 512);
-       if (rc) {
-               dev_err(&pdev->dev, "failed to set the maximum segment size\n");
-               return rc;
-       }
-
        rc = init_controller(hpriv->mmio_base, hpriv->cached_hctl);
        if (rc) {
                dev_err(&pdev->dev, "failed to initialize controller\n");
index 29f102d..2116079 100644 (file)
@@ -533,9 +533,10 @@ static void he_init_tx_lbfp(struct he_dev *he_dev)
 
 static int he_init_tpdrq(struct he_dev *he_dev)
 {
-       he_dev->tpdrq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev,
-                                                CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq),
-                                                &he_dev->tpdrq_phys, GFP_KERNEL);
+       he_dev->tpdrq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
+                                               CONFIG_TPDRQ_SIZE * sizeof(struct he_tpdrq),
+                                               &he_dev->tpdrq_phys,
+                                               GFP_KERNEL);
        if (he_dev->tpdrq_base == NULL) {
                hprintk("failed to alloc tpdrq\n");
                return -ENOMEM;
@@ -717,7 +718,7 @@ static int he_init_cs_block_rcm(struct he_dev *he_dev)
                        instead of '/ 512', use '>> 9' to prevent a call
                        to divdu3 on x86 platforms
                */
-               rate_cps = (unsigned long long) (1 << exp) * (man + 512) >> 9;
+               rate_cps = (unsigned long long) (1UL << exp) * (man + 512) >> 9;
 
                if (rate_cps < 10)
                        rate_cps = 10;  /* 2.2.1 minimum payload rate is 10 cps */
@@ -805,9 +806,9 @@ static int he_init_group(struct he_dev *he_dev, int group)
                goto out_free_rbpl_virt;
        }
 
-       he_dev->rbpl_base = dma_zalloc_coherent(&he_dev->pci_dev->dev,
-                                               CONFIG_RBPL_SIZE * sizeof(struct he_rbp),
-                                               &he_dev->rbpl_phys, GFP_KERNEL);
+       he_dev->rbpl_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
+                                              CONFIG_RBPL_SIZE * sizeof(struct he_rbp),
+                                              &he_dev->rbpl_phys, GFP_KERNEL);
        if (he_dev->rbpl_base == NULL) {
                hprintk("failed to alloc rbpl_base\n");
                goto out_destroy_rbpl_pool;
@@ -844,9 +845,9 @@ static int he_init_group(struct he_dev *he_dev, int group)
 
        /* rx buffer ready queue */
 
-       he_dev->rbrq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev,
-                                               CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
-                                               &he_dev->rbrq_phys, GFP_KERNEL);
+       he_dev->rbrq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
+                                              CONFIG_RBRQ_SIZE * sizeof(struct he_rbrq),
+                                              &he_dev->rbrq_phys, GFP_KERNEL);
        if (he_dev->rbrq_base == NULL) {
                hprintk("failed to allocate rbrq\n");
                goto out_free_rbpl;
@@ -868,9 +869,9 @@ static int he_init_group(struct he_dev *he_dev, int group)
 
        /* tx buffer ready queue */
 
-       he_dev->tbrq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev,
-                                               CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
-                                               &he_dev->tbrq_phys, GFP_KERNEL);
+       he_dev->tbrq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
+                                              CONFIG_TBRQ_SIZE * sizeof(struct he_tbrq),
+                                              &he_dev->tbrq_phys, GFP_KERNEL);
        if (he_dev->tbrq_base == NULL) {
                hprintk("failed to allocate tbrq\n");
                goto out_free_rbpq_base;
@@ -913,11 +914,9 @@ static int he_init_irq(struct he_dev *he_dev)
        /* 2.9.3.5  tail offset for each interrupt queue is located after the
                    end of the interrupt queue */
 
-       he_dev->irq_base = dma_zalloc_coherent(&he_dev->pci_dev->dev,
-                                              (CONFIG_IRQ_SIZE + 1)
-                                              * sizeof(struct he_irq),
-                                              &he_dev->irq_phys,
-                                              GFP_KERNEL);
+       he_dev->irq_base = dma_alloc_coherent(&he_dev->pci_dev->dev,
+                                             (CONFIG_IRQ_SIZE + 1) * sizeof(struct he_irq),
+                                             &he_dev->irq_phys, GFP_KERNEL);
        if (he_dev->irq_base == NULL) {
                hprintk("failed to allocate irq\n");
                return -ENOMEM;
@@ -1464,9 +1463,9 @@ static int he_start(struct atm_dev *dev)
 
        /* host status page */
 
-       he_dev->hsp = dma_zalloc_coherent(&he_dev->pci_dev->dev,
-                                         sizeof(struct he_hsp),
-                                         &he_dev->hsp_phys, GFP_KERNEL);
+       he_dev->hsp = dma_alloc_coherent(&he_dev->pci_dev->dev,
+                                        sizeof(struct he_hsp),
+                                        &he_dev->hsp_phys, GFP_KERNEL);
        if (he_dev->hsp == NULL) {
                hprintk("failed to allocate host status page\n");
                return -ENOMEM;
index 6e73714..43a1457 100644 (file)
@@ -641,8 +641,8 @@ alloc_scq(struct idt77252_dev *card, int class)
        scq = kzalloc(sizeof(struct scq_info), GFP_KERNEL);
        if (!scq)
                return NULL;
-       scq->base = dma_zalloc_coherent(&card->pcidev->dev, SCQ_SIZE,
-                                       &scq->paddr, GFP_KERNEL);
+       scq->base = dma_alloc_coherent(&card->pcidev->dev, SCQ_SIZE,
+                                      &scq->paddr, GFP_KERNEL);
        if (scq->base == NULL) {
                kfree(scq);
                return NULL;
@@ -971,8 +971,8 @@ init_rsq(struct idt77252_dev *card)
 {
        struct rsq_entry *rsqe;
 
-       card->rsq.base = dma_zalloc_coherent(&card->pcidev->dev, RSQSIZE,
-                                            &card->rsq.paddr, GFP_KERNEL);
+       card->rsq.base = dma_alloc_coherent(&card->pcidev->dev, RSQSIZE,
+                                           &card->rsq.paddr, GFP_KERNEL);
        if (card->rsq.base == NULL) {
                printk("%s: can't allocate RSQ.\n", card->name);
                return -1;
@@ -3390,10 +3390,10 @@ static int init_card(struct atm_dev *dev)
        writel(0, SAR_REG_GP);
 
        /* Initialize RAW Cell Handle Register  */
-       card->raw_cell_hnd = dma_zalloc_coherent(&card->pcidev->dev,
-                                                2 * sizeof(u32),
-                                                &card->raw_cell_paddr,
-                                                GFP_KERNEL);
+       card->raw_cell_hnd = dma_alloc_coherent(&card->pcidev->dev,
+                                               2 * sizeof(u32),
+                                               &card->raw_cell_paddr,
+                                               GFP_KERNEL);
        if (!card->raw_cell_hnd) {
                printk("%s: memory allocation failure.\n", card->name);
                deinit_card(card);
index a43276c..21393ec 100644 (file)
@@ -509,7 +509,7 @@ static int ht16k33_remove(struct i2c_client *client)
        struct ht16k33_priv *priv = i2c_get_clientdata(client);
        struct ht16k33_fbdev *fbdev = &priv->fbdev;
 
-       cancel_delayed_work(&fbdev->work);
+       cancel_delayed_work_sync(&fbdev->work);
        unregister_framebuffer(fbdev->info);
        framebuffer_release(fbdev->info);
        free_page((unsigned long) fbdev->buffer);
index cf78fa6..a735953 100644 (file)
@@ -79,8 +79,7 @@ static void cache_size(struct cacheinfo *this_leaf, struct device_node *np)
        ct_idx = get_cacheinfo_idx(this_leaf->type);
        propname = cache_type_info[ct_idx].size_prop;
 
-       if (of_property_read_u32(np, propname, &this_leaf->size))
-               this_leaf->size = 0;
+       of_property_read_u32(np, propname, &this_leaf->size);
 }
 
 /* not cache_line_size() because that's a macro in include/linux/cache.h */
@@ -114,8 +113,7 @@ static void cache_nr_sets(struct cacheinfo *this_leaf, struct device_node *np)
        ct_idx = get_cacheinfo_idx(this_leaf->type);
        propname = cache_type_info[ct_idx].nr_sets_prop;
 
-       if (of_property_read_u32(np, propname, &this_leaf->number_of_sets))
-               this_leaf->number_of_sets = 0;
+       of_property_read_u32(np, propname, &this_leaf->number_of_sets);
 }
 
 static void cache_associativity(struct cacheinfo *this_leaf)
index a690fd4..0992e67 100644 (file)
@@ -32,6 +32,7 @@
 #include <trace/events/power.h>
 #include <linux/cpufreq.h>
 #include <linux/cpuidle.h>
+#include <linux/devfreq.h>
 #include <linux/timer.h>
 
 #include "../base.h"
@@ -1078,6 +1079,7 @@ void dpm_resume(pm_message_t state)
        dpm_show_time(starttime, state, 0, NULL);
 
        cpufreq_resume();
+       devfreq_resume();
        trace_suspend_resume(TPS("dpm_resume"), state.event, false);
 }
 
@@ -1852,6 +1854,7 @@ int dpm_suspend(pm_message_t state)
        trace_suspend_resume(TPS("dpm_suspend"), state.event, true);
        might_sleep();
 
+       devfreq_suspend();
        cpufreq_suspend();
 
        mutex_lock(&dpm_list_mtx);
index 7062469..ccd296d 100644 (file)
@@ -95,7 +95,7 @@ static void __update_runtime_status(struct device *dev, enum rpm_status status)
 static void pm_runtime_deactivate_timer(struct device *dev)
 {
        if (dev->power.timer_expires > 0) {
-               hrtimer_cancel(&dev->power.suspend_timer);
+               hrtimer_try_to_cancel(&dev->power.suspend_timer);
                dev->power.timer_expires = 0;
        }
 }
@@ -121,7 +121,7 @@ static void pm_runtime_cancel_pending(struct device *dev)
  * Compute the autosuspend-delay expiration time based on the device's
  * power.last_busy time.  If the delay has already expired or is disabled
  * (negative) or the power.use_autosuspend flag isn't set, return 0.
- * Otherwise return the expiration time in jiffies (adjusted to be nonzero).
+ * Otherwise return the expiration time in nanoseconds (adjusted to be nonzero).
  *
  * This function may be called either with or without dev->power.lock held.
  * Either way it can be racy, since power.last_busy may be updated at any time.
@@ -130,7 +130,7 @@ u64 pm_runtime_autosuspend_expiration(struct device *dev)
 {
        int autosuspend_delay;
        u64 last_busy, expires = 0;
-       u64 now = ktime_to_ns(ktime_get());
+       u64 now = ktime_get_mono_fast_ns();
 
        if (!dev->power.use_autosuspend)
                goto out;
@@ -141,7 +141,7 @@ u64 pm_runtime_autosuspend_expiration(struct device *dev)
 
        last_busy = READ_ONCE(dev->power.last_busy);
 
-       expires = last_busy + autosuspend_delay * NSEC_PER_MSEC;
+       expires = last_busy + (u64)autosuspend_delay * NSEC_PER_MSEC;
        if (expires <= now)
                expires = 0;    /* Already expired. */
 
@@ -525,7 +525,7 @@ static int rpm_suspend(struct device *dev, int rpmflags)
                                 * We add a slack of 25% to gather wakeups
                                 * without sacrificing the granularity.
                                 */
-                               u64 slack = READ_ONCE(dev->power.autosuspend_delay) *
+                               u64 slack = (u64)READ_ONCE(dev->power.autosuspend_delay) *
                                                    (NSEC_PER_MSEC >> 2);
 
                                dev->power.timer_expires = expires;
@@ -905,8 +905,11 @@ static enum hrtimer_restart  pm_suspend_timer_fn(struct hrtimer *timer)
        spin_lock_irqsave(&dev->power.lock, flags);
 
        expires = dev->power.timer_expires;
-       /* If 'expire' is after 'jiffies' we've been called too early. */
-       if (expires > 0 && expires < ktime_to_ns(ktime_get())) {
+       /*
+        * If 'expires' is after the current time, we've been called
+        * too early.
+        */
+       if (expires > 0 && expires < ktime_get_mono_fast_ns()) {
                dev->power.timer_expires = 0;
                rpm_suspend(dev, dev->power.timer_autosuspends ?
                    (RPM_ASYNC | RPM_AUTO) : RPM_ASYNC);
@@ -925,7 +928,7 @@ static enum hrtimer_restart  pm_suspend_timer_fn(struct hrtimer *timer)
 int pm_schedule_suspend(struct device *dev, unsigned int delay)
 {
        unsigned long flags;
-       ktime_t expires;
+       u64 expires;
        int retval;
 
        spin_lock_irqsave(&dev->power.lock, flags);
@@ -942,8 +945,8 @@ int pm_schedule_suspend(struct device *dev, unsigned int delay)
        /* Other scheduled or pending requests need to be canceled. */
        pm_runtime_cancel_pending(dev);
 
-       expires = ktime_add(ktime_get(), ms_to_ktime(delay));
-       dev->power.timer_expires = ktime_to_ns(expires);
+       expires = ktime_get_mono_fast_ns() + (u64)delay * NSEC_PER_MSEC;
+       dev->power.timer_expires = expires;
        dev->power.timer_autosuspends = 0;
        hrtimer_start(&dev->power.suspend_timer, expires, HRTIMER_MODE_ABS);
 
index 1bd1145..330c1f7 100644 (file)
@@ -108,6 +108,9 @@ static void regmap_irq_sync_unlock(struct irq_data *data)
         * suppress pointless writes.
         */
        for (i = 0; i < d->chip->num_regs; i++) {
+               if (!d->chip->mask_base)
+                       continue;
+
                reg = d->chip->mask_base +
                        (i * map->reg_stride * d->irq_reg_stride);
                if (d->chip->mask_invert) {
@@ -258,7 +261,7 @@ static int regmap_irq_set_type(struct irq_data *data, unsigned int type)
        const struct regmap_irq_type *t = &irq_data->type;
 
        if ((t->types_supported & type) != type)
-               return -ENOTSUPP;
+               return 0;
 
        reg = t->type_reg_offset / map->reg_stride;
 
@@ -588,6 +591,9 @@ int regmap_add_irq_chip(struct regmap *map, int irq, int irq_flags,
        /* Mask all the interrupts by default */
        for (i = 0; i < chip->num_regs; i++) {
                d->mask_buf[i] = d->mask_buf_def[i];
+               if (!chip->mask_base)
+                       continue;
+
                reg = chip->mask_base +
                        (i * map->reg_stride * d->irq_reg_stride);
                if (chip->mask_invert)
index 6f2856c..55481b4 100644 (file)
@@ -4075,7 +4075,7 @@ static unsigned int floppy_check_events(struct gendisk *disk,
 
        if (time_after(jiffies, UDRS->last_checked + UDP->checkfreq)) {
                if (lock_fdc(drive))
-                       return -EINTR;
+                       return 0;
                poll_drive(false, 0);
                process_fd_request();
        }
index b8a0720..cf55389 100644 (file)
@@ -1190,6 +1190,12 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
                goto out_unlock;
        }
 
+       if (lo->lo_offset != info->lo_offset ||
+           lo->lo_sizelimit != info->lo_sizelimit) {
+               sync_blockdev(lo->lo_device);
+               kill_bdev(lo->lo_device);
+       }
+
        /* I/O need to be drained during transfer transition */
        blk_mq_freeze_queue(lo->lo_queue);
 
@@ -1218,6 +1224,14 @@ loop_set_status(struct loop_device *lo, const struct loop_info64 *info)
 
        if (lo->lo_offset != info->lo_offset ||
            lo->lo_sizelimit != info->lo_sizelimit) {
+               /* kill_bdev should have truncated all the pages */
+               if (lo->lo_device->bd_inode->i_mapping->nrpages) {
+                       err = -EAGAIN;
+                       pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
+                               __func__, lo->lo_number, lo->lo_file_name,
+                               lo->lo_device->bd_inode->i_mapping->nrpages);
+                       goto out_unfreeze;
+               }
                if (figure_loop_size(lo, info->lo_offset, info->lo_sizelimit)) {
                        err = -EFBIG;
                        goto out_unfreeze;
@@ -1443,22 +1457,39 @@ static int loop_set_dio(struct loop_device *lo, unsigned long arg)
 
 static int loop_set_block_size(struct loop_device *lo, unsigned long arg)
 {
+       int err = 0;
+
        if (lo->lo_state != Lo_bound)
                return -ENXIO;
 
        if (arg < 512 || arg > PAGE_SIZE || !is_power_of_2(arg))
                return -EINVAL;
 
+       if (lo->lo_queue->limits.logical_block_size != arg) {
+               sync_blockdev(lo->lo_device);
+               kill_bdev(lo->lo_device);
+       }
+
        blk_mq_freeze_queue(lo->lo_queue);
 
+       /* kill_bdev should have truncated all the pages */
+       if (lo->lo_queue->limits.logical_block_size != arg &&
+                       lo->lo_device->bd_inode->i_mapping->nrpages) {
+               err = -EAGAIN;
+               pr_warn("%s: loop%d (%s) has still dirty pages (nrpages=%lu)\n",
+                       __func__, lo->lo_number, lo->lo_file_name,
+                       lo->lo_device->bd_inode->i_mapping->nrpages);
+               goto out_unfreeze;
+       }
+
        blk_queue_logical_block_size(lo->lo_queue, arg);
        blk_queue_physical_block_size(lo->lo_queue, arg);
        blk_queue_io_min(lo->lo_queue, arg);
        loop_update_dio(lo);
-
+out_unfreeze:
        blk_mq_unfreeze_queue(lo->lo_queue);
 
-       return 0;
+       return err;
 }
 
 static int lo_simple_ioctl(struct loop_device *lo, unsigned int cmd,
index 08696f5..7c9a949 100644 (file)
@@ -288,9 +288,10 @@ static void nbd_size_update(struct nbd_device *nbd)
        blk_queue_physical_block_size(nbd->disk->queue, config->blksize);
        set_capacity(nbd->disk, config->bytesize >> 9);
        if (bdev) {
-               if (bdev->bd_disk)
+               if (bdev->bd_disk) {
                        bd_set_size(bdev, config->bytesize);
-               else
+                       set_blocksize(bdev, config->blksize);
+               } else
                        bdev->bd_invalidated = 1;
                bdput(bdev);
        }
index b3df279..34b22d6 100644 (file)
@@ -97,6 +97,7 @@ void null_zone_reset(struct nullb_cmd *cmd, sector_t sector);
 #else
 static inline int null_zone_init(struct nullb_device *dev)
 {
+       pr_err("null_blk: CONFIG_BLK_DEV_ZONED not enabled\n");
        return -EINVAL;
 }
 static inline void null_zone_exit(struct nullb_device *dev) {}
index 8e5140b..1e92b61 100644 (file)
@@ -5986,7 +5986,6 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
        struct list_head *tmp;
        int dev_id;
        char opt_buf[6];
-       bool already = false;
        bool force = false;
        int ret;
 
@@ -6019,13 +6018,13 @@ static ssize_t do_rbd_remove(struct bus_type *bus,
                spin_lock_irq(&rbd_dev->lock);
                if (rbd_dev->open_count && !force)
                        ret = -EBUSY;
-               else
-                       already = test_and_set_bit(RBD_DEV_FLAG_REMOVING,
-                                                       &rbd_dev->flags);
+               else if (test_and_set_bit(RBD_DEV_FLAG_REMOVING,
+                                         &rbd_dev->flags))
+                       ret = -EINPROGRESS;
                spin_unlock_irq(&rbd_dev->lock);
        }
        spin_unlock(&rbd_dev_list_lock);
-       if (ret < 0 || already)
+       if (ret)
                return ret;
 
        if (force) {
index a10d573..ab893a7 100644 (file)
@@ -2641,8 +2641,8 @@ static int skd_cons_skcomp(struct skd_device *skdev)
                "comp pci_alloc, total bytes %zd entries %d\n",
                SKD_SKCOMP_SIZE, SKD_N_COMPLETION_ENTRY);
 
-       skcomp = dma_zalloc_coherent(&skdev->pdev->dev, SKD_SKCOMP_SIZE,
-                                    &skdev->cq_dma_address, GFP_KERNEL);
+       skcomp = dma_alloc_coherent(&skdev->pdev->dev, SKD_SKCOMP_SIZE,
+                                   &skdev->cq_dma_address, GFP_KERNEL);
 
        if (skcomp == NULL) {
                rc = -ENOMEM;
index 33c5cc8..04ca659 100644 (file)
@@ -316,11 +316,9 @@ static ssize_t idle_store(struct device *dev,
                 * See the comment in writeback_store.
                 */
                zram_slot_lock(zram, index);
-               if (!zram_allocated(zram, index) ||
-                               zram_test_flag(zram, index, ZRAM_UNDER_WB))
-                       goto next;
-               zram_set_flag(zram, index, ZRAM_IDLE);
-next:
+               if (zram_allocated(zram, index) &&
+                               !zram_test_flag(zram, index, ZRAM_UNDER_WB))
+                       zram_set_flag(zram, index, ZRAM_IDLE);
                zram_slot_unlock(zram, index);
        }
 
@@ -330,6 +328,41 @@ next:
 }
 
 #ifdef CONFIG_ZRAM_WRITEBACK
+static ssize_t writeback_limit_enable_store(struct device *dev,
+               struct device_attribute *attr, const char *buf, size_t len)
+{
+       struct zram *zram = dev_to_zram(dev);
+       u64 val;
+       ssize_t ret = -EINVAL;
+
+       if (kstrtoull(buf, 10, &val))
+               return ret;
+
+       down_read(&zram->init_lock);
+       spin_lock(&zram->wb_limit_lock);
+       zram->wb_limit_enable = val;
+       spin_unlock(&zram->wb_limit_lock);
+       up_read(&zram->init_lock);
+       ret = len;
+
+       return ret;
+}
+
+static ssize_t writeback_limit_enable_show(struct device *dev,
+               struct device_attribute *attr, char *buf)
+{
+       bool val;
+       struct zram *zram = dev_to_zram(dev);
+
+       down_read(&zram->init_lock);
+       spin_lock(&zram->wb_limit_lock);
+       val = zram->wb_limit_enable;
+       spin_unlock(&zram->wb_limit_lock);
+       up_read(&zram->init_lock);
+
+       return scnprintf(buf, PAGE_SIZE, "%d\n", val);
+}
+
 static ssize_t writeback_limit_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t len)
 {
@@ -341,9 +374,9 @@ static ssize_t writeback_limit_store(struct device *dev,
                return ret;
 
        down_read(&zram->init_lock);
-       atomic64_set(&zram->stats.bd_wb_limit, val);
-       if (val == 0)
-               zram->stop_writeback = false;
+       spin_lock(&zram->wb_limit_lock);
+       zram->bd_wb_limit = val;
+       spin_unlock(&zram->wb_limit_lock);
        up_read(&zram->init_lock);
        ret = len;
 
@@ -357,7 +390,9 @@ static ssize_t writeback_limit_show(struct device *dev,
        struct zram *zram = dev_to_zram(dev);
 
        down_read(&zram->init_lock);
-       val = atomic64_read(&zram->stats.bd_wb_limit);
+       spin_lock(&zram->wb_limit_lock);
+       val = zram->bd_wb_limit;
+       spin_unlock(&zram->wb_limit_lock);
        up_read(&zram->init_lock);
 
        return scnprintf(buf, PAGE_SIZE, "%llu\n", val);
@@ -588,8 +623,8 @@ static int read_from_bdev_async(struct zram *zram, struct bio_vec *bvec,
        return 1;
 }
 
-#define HUGE_WRITEBACK 0x1
-#define IDLE_WRITEBACK 0x2
+#define HUGE_WRITEBACK 1
+#define IDLE_WRITEBACK 2
 
 static ssize_t writeback_store(struct device *dev,
                struct device_attribute *attr, const char *buf, size_t len)
@@ -602,7 +637,7 @@ static ssize_t writeback_store(struct device *dev,
        struct page *page;
        ssize_t ret, sz;
        char mode_buf[8];
-       unsigned long mode = -1UL;
+       int mode = -1;
        unsigned long blk_idx = 0;
 
        sz = strscpy(mode_buf, buf, sizeof(mode_buf));
@@ -618,7 +653,7 @@ static ssize_t writeback_store(struct device *dev,
        else if (!strcmp(mode_buf, "huge"))
                mode = HUGE_WRITEBACK;
 
-       if (mode == -1UL)
+       if (mode == -1)
                return -EINVAL;
 
        down_read(&zram->init_lock);
@@ -645,10 +680,13 @@ static ssize_t writeback_store(struct device *dev,
                bvec.bv_len = PAGE_SIZE;
                bvec.bv_offset = 0;
 
-               if (zram->stop_writeback) {
+               spin_lock(&zram->wb_limit_lock);
+               if (zram->wb_limit_enable && !zram->bd_wb_limit) {
+                       spin_unlock(&zram->wb_limit_lock);
                        ret = -EIO;
                        break;
                }
+               spin_unlock(&zram->wb_limit_lock);
 
                if (!blk_idx) {
                        blk_idx = alloc_block_bdev(zram);
@@ -667,10 +705,11 @@ static ssize_t writeback_store(struct device *dev,
                                zram_test_flag(zram, index, ZRAM_UNDER_WB))
                        goto next;
 
-               if ((mode & IDLE_WRITEBACK &&
-                         !zram_test_flag(zram, index, ZRAM_IDLE)) &&
-                   (mode & HUGE_WRITEBACK &&
-                         !zram_test_flag(zram, index, ZRAM_HUGE)))
+               if (mode == IDLE_WRITEBACK &&
+                         !zram_test_flag(zram, index, ZRAM_IDLE))
+                       goto next;
+               if (mode == HUGE_WRITEBACK &&
+                         !zram_test_flag(zram, index, ZRAM_HUGE))
                        goto next;
                /*
                 * Clearing ZRAM_UNDER_WB is duty of caller.
@@ -732,11 +771,10 @@ static ssize_t writeback_store(struct device *dev,
                zram_set_element(zram, index, blk_idx);
                blk_idx = 0;
                atomic64_inc(&zram->stats.pages_stored);
-               if (atomic64_add_unless(&zram->stats.bd_wb_limit,
-                                       -1 << (PAGE_SHIFT - 12), 0)) {
-                       if (atomic64_read(&zram->stats.bd_wb_limit) == 0)
-                               zram->stop_writeback = true;
-               }
+               spin_lock(&zram->wb_limit_lock);
+               if (zram->wb_limit_enable && zram->bd_wb_limit > 0)
+                       zram->bd_wb_limit -=  1UL << (PAGE_SHIFT - 12);
+               spin_unlock(&zram->wb_limit_lock);
 next:
                zram_slot_unlock(zram, index);
        }
@@ -1812,6 +1850,7 @@ static DEVICE_ATTR_RW(comp_algorithm);
 static DEVICE_ATTR_RW(backing_dev);
 static DEVICE_ATTR_WO(writeback);
 static DEVICE_ATTR_RW(writeback_limit);
+static DEVICE_ATTR_RW(writeback_limit_enable);
 #endif
 
 static struct attribute *zram_disk_attrs[] = {
@@ -1828,6 +1867,7 @@ static struct attribute *zram_disk_attrs[] = {
        &dev_attr_backing_dev.attr,
        &dev_attr_writeback.attr,
        &dev_attr_writeback_limit.attr,
+       &dev_attr_writeback_limit_enable.attr,
 #endif
        &dev_attr_io_stat.attr,
        &dev_attr_mm_stat.attr,
@@ -1867,7 +1907,9 @@ static int zram_add(void)
        device_id = ret;
 
        init_rwsem(&zram->init_lock);
-
+#ifdef CONFIG_ZRAM_WRITEBACK
+       spin_lock_init(&zram->wb_limit_lock);
+#endif
        queue = blk_alloc_queue(GFP_KERNEL);
        if (!queue) {
                pr_err("Error allocating disk queue for device %d\n",
index 4bd3afd..f2fd46d 100644 (file)
@@ -86,7 +86,6 @@ struct zram_stats {
        atomic64_t bd_count;            /* no. of pages in backing device */
        atomic64_t bd_reads;            /* no. of reads from backing device */
        atomic64_t bd_writes;           /* no. of writes from backing device */
-       atomic64_t bd_wb_limit;         /* writeback limit of backing device */
 #endif
 };
 
@@ -114,8 +113,10 @@ struct zram {
         */
        bool claim; /* Protected by bdev->bd_mutex */
        struct file *backing_dev;
-       bool stop_writeback;
 #ifdef CONFIG_ZRAM_WRITEBACK
+       spinlock_t wb_limit_lock;
+       bool wb_limit_enable;
+       u64 bd_wb_limit;
        struct block_device *bdev;
        unsigned int old_block_size;
        unsigned long *bitmap;
index f94d335..d299ec7 100644 (file)
@@ -781,12 +781,12 @@ static const struct sysc_revision_quirk sysc_revision_quirks[] = {
        SYSC_QUIRK("smartreflex", 0, -1, 0x38, -1, 0x00000000, 0xffffffff,
                   SYSC_QUIRK_LEGACY_IDLE),
        SYSC_QUIRK("timer", 0, 0, 0x10, 0x14, 0x00000015, 0xffffffff,
-                  SYSC_QUIRK_LEGACY_IDLE),
+                  0),
        /* Some timers on omap4 and later */
        SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x50002100, 0xffffffff,
-                  SYSC_QUIRK_LEGACY_IDLE),
+                  0),
        SYSC_QUIRK("timer", 0, 0, 0x10, -1, 0x4fff1301, 0xffff00ff,
-                  SYSC_QUIRK_LEGACY_IDLE),
+                  0),
        SYSC_QUIRK("uart", 0, 0x50, 0x54, 0x58, 0x00000052, 0xffffffff,
                   SYSC_QUIRK_LEGACY_IDLE),
        /* Uarts on omap4 and later */
index a74ce88..c518659 100644 (file)
@@ -32,6 +32,7 @@
 #include <linux/moduleparam.h>
 #include <linux/workqueue.h>
 #include <linux/uuid.h>
+#include <linux/nospec.h>
 
 #define IPMI_DRIVER_VERSION "39.2"
 
@@ -62,7 +63,8 @@ static void ipmi_debug_msg(const char *title, unsigned char *data,
 { }
 #endif
 
-static int initialized;
+static bool initialized;
+static bool drvregistered;
 
 enum ipmi_panic_event_op {
        IPMI_SEND_PANIC_EVENT_NONE,
@@ -612,7 +614,7 @@ static DEFINE_MUTEX(ipmidriver_mutex);
 
 static LIST_HEAD(ipmi_interfaces);
 static DEFINE_MUTEX(ipmi_interfaces_mutex);
-DEFINE_STATIC_SRCU(ipmi_interfaces_srcu);
+struct srcu_struct ipmi_interfaces_srcu;
 
 /*
  * List of watchers that want to know when smi's are added and deleted.
@@ -720,7 +722,15 @@ struct watcher_entry {
 int ipmi_smi_watcher_register(struct ipmi_smi_watcher *watcher)
 {
        struct ipmi_smi *intf;
-       int index;
+       int index, rv;
+
+       /*
+        * Make sure the driver is actually initialized, this handles
+        * problems with initialization order.
+        */
+       rv = ipmi_init_msghandler();
+       if (rv)
+               return rv;
 
        mutex_lock(&smi_watchers_mutex);
 
@@ -884,7 +894,7 @@ static int deliver_response(struct ipmi_smi *intf, struct ipmi_recv_msg *msg)
 
                if (user) {
                        user->handler->ipmi_recv_hndl(msg, user->handler_data);
-                       release_ipmi_user(msg->user, index);
+                       release_ipmi_user(user, index);
                } else {
                        /* User went away, give up. */
                        ipmi_free_recv_msg(msg);
@@ -1076,7 +1086,7 @@ int ipmi_create_user(unsigned int          if_num,
 {
        unsigned long flags;
        struct ipmi_user *new_user;
-       int           rv = 0, index;
+       int           rv, index;
        struct ipmi_smi *intf;
 
        /*
@@ -1094,18 +1104,9 @@ int ipmi_create_user(unsigned int          if_num,
         * Make sure the driver is actually initialized, this handles
         * problems with initialization order.
         */
-       if (!initialized) {
-               rv = ipmi_init_msghandler();
-               if (rv)
-                       return rv;
-
-               /*
-                * The init code doesn't return an error if it was turned
-                * off, but it won't initialize.  Check that.
-                */
-               if (!initialized)
-                       return -ENODEV;
-       }
+       rv = ipmi_init_msghandler();
+       if (rv)
+               return rv;
 
        new_user = kmalloc(sizeof(*new_user), GFP_KERNEL);
        if (!new_user)
@@ -1183,6 +1184,7 @@ EXPORT_SYMBOL(ipmi_get_smi_info);
 static void free_user(struct kref *ref)
 {
        struct ipmi_user *user = container_of(ref, struct ipmi_user, refcount);
+       cleanup_srcu_struct(&user->release_barrier);
        kfree(user);
 }
 
@@ -1259,7 +1261,6 @@ int ipmi_destroy_user(struct ipmi_user *user)
 {
        _ipmi_destroy_user(user);
 
-       cleanup_srcu_struct(&user->release_barrier);
        kref_put(&user->refcount, free_user);
 
        return 0;
@@ -1298,10 +1299,12 @@ int ipmi_set_my_address(struct ipmi_user *user,
        if (!user)
                return -ENODEV;
 
-       if (channel >= IPMI_MAX_CHANNELS)
+       if (channel >= IPMI_MAX_CHANNELS) {
                rv = -EINVAL;
-       else
+       } else {
+               channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
                user->intf->addrinfo[channel].address = address;
+       }
        release_ipmi_user(user, index);
 
        return rv;
@@ -1318,10 +1321,12 @@ int ipmi_get_my_address(struct ipmi_user *user,
        if (!user)
                return -ENODEV;
 
-       if (channel >= IPMI_MAX_CHANNELS)
+       if (channel >= IPMI_MAX_CHANNELS) {
                rv = -EINVAL;
-       else
+       } else {
+               channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
                *address = user->intf->addrinfo[channel].address;
+       }
        release_ipmi_user(user, index);
 
        return rv;
@@ -1338,10 +1343,12 @@ int ipmi_set_my_LUN(struct ipmi_user *user,
        if (!user)
                return -ENODEV;
 
-       if (channel >= IPMI_MAX_CHANNELS)
+       if (channel >= IPMI_MAX_CHANNELS) {
                rv = -EINVAL;
-       else
+       } else {
+               channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
                user->intf->addrinfo[channel].lun = LUN & 0x3;
+       }
        release_ipmi_user(user, index);
 
        return rv;
@@ -1358,10 +1365,12 @@ int ipmi_get_my_LUN(struct ipmi_user *user,
        if (!user)
                return -ENODEV;
 
-       if (channel >= IPMI_MAX_CHANNELS)
+       if (channel >= IPMI_MAX_CHANNELS) {
                rv = -EINVAL;
-       else
+       } else {
+               channel = array_index_nospec(channel, IPMI_MAX_CHANNELS);
                *address = user->intf->addrinfo[channel].lun;
+       }
        release_ipmi_user(user, index);
 
        return rv;
@@ -2184,6 +2193,7 @@ static int check_addr(struct ipmi_smi  *intf,
 {
        if (addr->channel >= IPMI_MAX_CHANNELS)
                return -EINVAL;
+       addr->channel = array_index_nospec(addr->channel, IPMI_MAX_CHANNELS);
        *lun = intf->addrinfo[addr->channel].lun;
        *saddr = intf->addrinfo[addr->channel].address;
        return 0;
@@ -3291,17 +3301,9 @@ int ipmi_register_smi(const struct ipmi_smi_handlers *handlers,
         * Make sure the driver is actually initialized, this handles
         * problems with initialization order.
         */
-       if (!initialized) {
-               rv = ipmi_init_msghandler();
-               if (rv)
-                       return rv;
-               /*
-                * The init code doesn't return an error if it was turned
-                * off, but it won't initialize.  Check that.
-                */
-               if (!initialized)
-                       return -ENODEV;
-       }
+       rv = ipmi_init_msghandler();
+       if (rv)
+               return rv;
 
        intf = kzalloc(sizeof(*intf), GFP_KERNEL);
        if (!intf)
@@ -5017,6 +5019,22 @@ static int panic_event(struct notifier_block *this,
        return NOTIFY_DONE;
 }
 
+/* Must be called with ipmi_interfaces_mutex held. */
+static int ipmi_register_driver(void)
+{
+       int rv;
+
+       if (drvregistered)
+               return 0;
+
+       rv = driver_register(&ipmidriver.driver);
+       if (rv)
+               pr_err("Could not register IPMI driver\n");
+       else
+               drvregistered = true;
+       return rv;
+}
+
 static struct notifier_block panic_block = {
        .notifier_call  = panic_event,
        .next           = NULL,
@@ -5027,66 +5045,75 @@ static int ipmi_init_msghandler(void)
 {
        int rv;
 
+       mutex_lock(&ipmi_interfaces_mutex);
+       rv = ipmi_register_driver();
+       if (rv)
+               goto out;
        if (initialized)
-               return 0;
-
-       rv = driver_register(&ipmidriver.driver);
-       if (rv) {
-               pr_err("Could not register IPMI driver\n");
-               return rv;
-       }
+               goto out;
 
-       pr_info("version " IPMI_DRIVER_VERSION "\n");
+       init_srcu_struct(&ipmi_interfaces_srcu);
 
        timer_setup(&ipmi_timer, ipmi_timeout, 0);
        mod_timer(&ipmi_timer, jiffies + IPMI_TIMEOUT_JIFFIES);
 
        atomic_notifier_chain_register(&panic_notifier_list, &panic_block);
 
-       initialized = 1;
+       initialized = true;
 
-       return 0;
+out:
+       mutex_unlock(&ipmi_interfaces_mutex);
+       return rv;
 }
 
 static int __init ipmi_init_msghandler_mod(void)
 {
-       ipmi_init_msghandler();
-       return 0;
+       int rv;
+
+       pr_info("version " IPMI_DRIVER_VERSION "\n");
+
+       mutex_lock(&ipmi_interfaces_mutex);
+       rv = ipmi_register_driver();
+       mutex_unlock(&ipmi_interfaces_mutex);
+
+       return rv;
 }
 
 static void __exit cleanup_ipmi(void)
 {
        int count;
 
-       if (!initialized)
-               return;
-
-       atomic_notifier_chain_unregister(&panic_notifier_list, &panic_block);
+       if (initialized) {
+               atomic_notifier_chain_unregister(&panic_notifier_list,
+                                                &panic_block);
 
-       /*
-        * This can't be called if any interfaces exist, so no worry
-        * about shutting down the interfaces.
-        */
+               /*
+                * This can't be called if any interfaces exist, so no worry
+                * about shutting down the interfaces.
+                */
 
-       /*
-        * Tell the timer to stop, then wait for it to stop.  This
-        * avoids problems with race conditions removing the timer
-        * here.
-        */
-       atomic_inc(&stop_operation);
-       del_timer_sync(&ipmi_timer);
+               /*
+                * Tell the timer to stop, then wait for it to stop.  This
+                * avoids problems with race conditions removing the timer
+                * here.
+                */
+               atomic_inc(&stop_operation);
+               del_timer_sync(&ipmi_timer);
 
-       driver_unregister(&ipmidriver.driver);
+               initialized = false;
 
-       initialized = 0;
+               /* Check for buffer leaks. */
+               count = atomic_read(&smi_msg_inuse_count);
+               if (count != 0)
+                       pr_warn("SMI message count %d at exit\n", count);
+               count = atomic_read(&recv_msg_inuse_count);
+               if (count != 0)
+                       pr_warn("recv message count %d at exit\n", count);
 
-       /* Check for buffer leaks. */
-       count = atomic_read(&smi_msg_inuse_count);
-       if (count != 0)
-               pr_warn("SMI message count %d at exit\n", count);
-       count = atomic_read(&recv_msg_inuse_count);
-       if (count != 0)
-               pr_warn("recv message count %d at exit\n", count);
+               cleanup_srcu_struct(&ipmi_interfaces_srcu);
+       }
+       if (drvregistered)
+               driver_unregister(&ipmidriver.driver);
 }
 module_exit(cleanup_ipmi);
 
index ca9528c..b7a1ae2 100644 (file)
@@ -632,8 +632,9 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
 
                /* Remove the multi-part read marker. */
                len -= 2;
+               data += 2;
                for (i = 0; i < len; i++)
-                       ssif_info->data[i] = data[i+2];
+                       ssif_info->data[i] = data[i];
                ssif_info->multi_len = len;
                ssif_info->multi_pos = 1;
 
@@ -661,8 +662,19 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                }
 
                blocknum = data[0];
+               len--;
+               data++;
+
+               if (blocknum != 0xff && len != 31) {
+                   /* All blocks but the last must have 31 data bytes. */
+                       result = -EIO;
+                       if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
+                               pr_info("Received middle message <31\n");
 
-               if (ssif_info->multi_len + len - 1 > IPMI_MAX_MSG_LENGTH) {
+                       goto continue_op;
+               }
+
+               if (ssif_info->multi_len + len > IPMI_MAX_MSG_LENGTH) {
                        /* Received message too big, abort the operation. */
                        result = -E2BIG;
                        if (ssif_info->ssif_debug & SSIF_DEBUG_MSG)
@@ -671,16 +683,14 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                        goto continue_op;
                }
 
-               /* Remove the blocknum from the data. */
-               len--;
                for (i = 0; i < len; i++)
-                       ssif_info->data[i + ssif_info->multi_len] = data[i + 1];
+                       ssif_info->data[i + ssif_info->multi_len] = data[i];
                ssif_info->multi_len += len;
                if (blocknum == 0xff) {
                        /* End of read */
                        len = ssif_info->multi_len;
                        data = ssif_info->data;
-               } else if (blocknum + 1 != ssif_info->multi_pos) {
+               } else if (blocknum != ssif_info->multi_pos) {
                        /*
                         * Out of sequence block, just abort.  Block
                         * numbers start at zero for the second block,
@@ -707,6 +717,7 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                }
        }
 
+ continue_op:
        if (result < 0) {
                ssif_inc_stat(ssif_info, receive_errors);
        } else {
@@ -714,8 +725,6 @@ static void msg_done_handler(struct ssif_info *ssif_info, int result,
                ssif_inc_stat(ssif_info, received_message_parts);
        }
 
-
- continue_op:
        if (ssif_info->ssif_debug & SSIF_DEBUG_STATE)
                pr_info("DONE 1: state = %d, result=%d\n",
                        ssif_info->ssif_state, result);
index b5e3103..e43c876 100644 (file)
@@ -59,6 +59,7 @@
 #include <linux/mutex.h>
 #include <linux/delay.h>
 #include <linux/serial_8250.h>
+#include <linux/nospec.h>
 #include "smapi.h"
 #include "mwavedd.h"
 #include "3780i.h"
@@ -289,6 +290,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                                ipcnum);
                                return -EINVAL;
                        }
+                       ipcnum = array_index_nospec(ipcnum,
+                                                   ARRAY_SIZE(pDrvData->IPCs));
                        PRINTK_3(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl IOCTL_MW_REGISTER_IPC"
                                " ipcnum %x entry usIntCount %x\n",
@@ -317,6 +320,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                                " Invalid ipcnum %x\n", ipcnum);
                                return -EINVAL;
                        }
+                       ipcnum = array_index_nospec(ipcnum,
+                                                   ARRAY_SIZE(pDrvData->IPCs));
                        PRINTK_3(TRACE_MWAVE,
                                "mwavedd::mwave_ioctl IOCTL_MW_GET_IPC"
                                " ipcnum %x, usIntCount %x\n",
@@ -383,6 +388,8 @@ static long mwave_ioctl(struct file *file, unsigned int iocmd,
                                                ipcnum);
                                return -EINVAL;
                        }
+                       ipcnum = array_index_nospec(ipcnum,
+                                                   ARRAY_SIZE(pDrvData->IPCs));
                        mutex_lock(&mwave_mutex);
                        if (pDrvData->IPCs[ipcnum].bIsEnabled == true) {
                                pDrvData->IPCs[ipcnum].bIsEnabled = false;
index e5b2fe8..e705aab 100644 (file)
@@ -290,10 +290,15 @@ config COMMON_CLK_BD718XX
          This driver supports ROHM BD71837 and ROHM BD71847
          PMICs clock gates.
 
+config COMMON_CLK_FIXED_MMIO
+       bool "Clock driver for Memory Mapped Fixed values"
+       depends on COMMON_CLK && OF
+       help
+         Support for Memory Mapped IO Fixed clocks
+
 source "drivers/clk/actions/Kconfig"
 source "drivers/clk/bcm/Kconfig"
 source "drivers/clk/hisilicon/Kconfig"
-source "drivers/clk/imx/Kconfig"
 source "drivers/clk/imgtec/Kconfig"
 source "drivers/clk/imx/Kconfig"
 source "drivers/clk/ingenic/Kconfig"
index 8a9440a..1db1336 100644 (file)
@@ -27,6 +27,7 @@ obj-$(CONFIG_COMMON_CLK_CDCE925)      += clk-cdce925.o
 obj-$(CONFIG_ARCH_CLPS711X)            += clk-clps711x.o
 obj-$(CONFIG_COMMON_CLK_CS2000_CP)     += clk-cs2000-cp.o
 obj-$(CONFIG_ARCH_EFM32)               += clk-efm32gg.o
+obj-$(CONFIG_COMMON_CLK_FIXED_MMIO)    += clk-fixed-mmio.o
 obj-$(CONFIG_COMMON_CLK_GEMINI)                += clk-gemini.o
 obj-$(CONFIG_COMMON_CLK_ASPEED)                += clk-aspeed.o
 obj-$(CONFIG_ARCH_HIGHBANK)            += clk-highbank.o
@@ -78,7 +79,7 @@ obj-$(CONFIG_ARCH_K3)                 += keystone/
 obj-$(CONFIG_ARCH_KEYSTONE)            += keystone/
 obj-$(CONFIG_MACH_LOONGSON32)          += loongson1/
 obj-y                                  += mediatek/
-obj-$(CONFIG_COMMON_CLK_AMLOGIC)       += meson/
+obj-$(CONFIG_ARCH_MESON)               += meson/
 obj-$(CONFIG_MACH_PIC32)               += microchip/
 ifeq ($(CONFIG_COMMON_CLK), y)
 obj-$(CONFIG_ARCH_MMP)                 += mmp/
index 04f0a63..5b45ca3 100644 (file)
@@ -9,6 +9,11 @@ if CLK_ACTIONS
 
 # SoC Drivers
 
+config CLK_OWL_S500
+       bool "Support for the Actions Semi OWL S500 clocks"
+       depends on ARCH_ACTIONS || COMPILE_TEST
+       default ARCH_ACTIONS
+
 config CLK_OWL_S700
        bool "Support for the Actions Semi OWL S700 clocks"
        depends on (ARM64 && ARCH_ACTIONS) || COMPILE_TEST
index ccfdf97..a2588e5 100644 (file)
@@ -10,5 +10,6 @@ clk-owl-y                     += owl-pll.o
 clk-owl-y                      += owl-reset.o
 
 # SoC support
+obj-$(CONFIG_CLK_OWL_S500)     += owl-s500.o
 obj-$(CONFIG_CLK_OWL_S700)     += owl-s700.o
 obj-$(CONFIG_CLK_OWL_S900)     += owl-s900.o
index 058e06d..02437bd 100644 (file)
@@ -179,7 +179,7 @@ static int owl_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 
        regmap_write(common->regmap, pll_hw->reg, reg);
 
-       udelay(PLL_STABILITY_WAIT_US);
+       udelay(pll_hw->delay);
 
        return 0;
 }
index 0aae30a..6fb0d45 100644 (file)
@@ -13,6 +13,8 @@
 
 #include "owl-common.h"
 
+#define OWL_PLL_DEF_DELAY      50
+
 /* last entry should have rate = 0 */
 struct clk_pll_table {
        unsigned int            val;
@@ -27,6 +29,7 @@ struct owl_pll_hw {
        u8                      width;
        u8                      min_mul;
        u8                      max_mul;
+       u8                      delay;
        const struct clk_pll_table *table;
 };
 
@@ -36,7 +39,7 @@ struct owl_pll {
 };
 
 #define OWL_PLL_HW(_reg, _bfreq, _bit_idx, _shift,                     \
-                  _width, _min_mul, _max_mul, _table)                  \
+                  _width, _min_mul, _max_mul, _delay, _table)          \
        {                                                               \
                .reg            = _reg,                                 \
                .bfreq          = _bfreq,                               \
@@ -45,6 +48,7 @@ struct owl_pll {
                .width          = _width,                               \
                .min_mul        = _min_mul,                             \
                .max_mul        = _max_mul,                             \
+               .delay          = _delay,                               \
                .table          = _table,                               \
        }
 
@@ -52,8 +56,8 @@ struct owl_pll {
                _shift, _width, _min_mul, _max_mul, _table, _flags)     \
        struct owl_pll _struct = {                                      \
                .pll_hw = OWL_PLL_HW(_reg, _bfreq, _bit_idx, _shift,    \
-                                    _width, _min_mul,                  \
-                                    _max_mul, _table),                 \
+                                    _width, _min_mul, _max_mul,        \
+                                    OWL_PLL_DEF_DELAY, _table),        \
                .common = {                                             \
                        .regmap = NULL,                                 \
                        .hw.init = CLK_HW_INIT(_name,                   \
@@ -67,8 +71,23 @@ struct owl_pll {
                _shift, _width, _min_mul, _max_mul, _table, _flags)     \
        struct owl_pll _struct = {                                      \
                .pll_hw = OWL_PLL_HW(_reg, _bfreq, _bit_idx, _shift,    \
-                                    _width, _min_mul,                  \
-                                    _max_mul, _table),                 \
+                                    _width, _min_mul, _max_mul,        \
+                                    OWL_PLL_DEF_DELAY, _table),        \
+               .common = {                                             \
+                       .regmap = NULL,                                 \
+                       .hw.init = CLK_HW_INIT_NO_PARENT(_name,         \
+                                              &owl_pll_ops,            \
+                                              _flags),                 \
+               },                                                      \
+       }
+
+#define OWL_PLL_NO_PARENT_DELAY(_struct, _name, _reg, _bfreq, _bit_idx,        \
+               _shift, _width, _min_mul, _max_mul, _delay, _table,     \
+               _flags)                                                 \
+       struct owl_pll _struct = {                                      \
+               .pll_hw = OWL_PLL_HW(_reg, _bfreq, _bit_idx, _shift,    \
+                                    _width, _min_mul,  _max_mul,       \
+                                    _delay, _table),                   \
                .common = {                                             \
                        .regmap = NULL,                                 \
                        .hw.init = CLK_HW_INIT_NO_PARENT(_name,         \
@@ -78,7 +97,6 @@ struct owl_pll {
        }
 
 #define mul_mask(m)            ((1 << ((m)->width)) - 1)
-#define PLL_STABILITY_WAIT_US  (50)
 
 static inline struct owl_pll *hw_to_owl_pll(const struct clk_hw *hw)
 {
diff --git a/drivers/clk/actions/owl-s500.c b/drivers/clk/actions/owl-s500.c
new file mode 100644 (file)
index 0000000..e2007ac
--- /dev/null
@@ -0,0 +1,525 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Actions Semi Owl S500 SoC clock driver
+ *
+ * Copyright (c) 2014 Actions Semi Inc.
+ * Author: David Liu <liuwei@actions-semi.com>
+ *
+ * Copyright (c) 2018 Linaro Ltd.
+ * Author: Manivannan Sadhasivam <manivannan.sadhasivam@linaro.org>
+ *
+ * Copyright (c) 2018 LSI-TEC - Caninos Loucos
+ * Author: Edgar Bernardi Righi <edgar.righi@lsitec.org.br>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+
+#include "owl-common.h"
+#include "owl-composite.h"
+#include "owl-divider.h"
+#include "owl-factor.h"
+#include "owl-fixed-factor.h"
+#include "owl-gate.h"
+#include "owl-mux.h"
+#include "owl-pll.h"
+
+#include <dt-bindings/clock/actions,s500-cmu.h>
+
+#define CMU_COREPLL                    (0x0000)
+#define CMU_DEVPLL                     (0x0004)
+#define CMU_DDRPLL                     (0x0008)
+#define CMU_NANDPLL                    (0x000C)
+#define CMU_DISPLAYPLL                 (0x0010)
+#define CMU_AUDIOPLL                   (0x0014)
+#define CMU_TVOUTPLL                   (0x0018)
+#define CMU_BUSCLK                     (0x001C)
+#define CMU_SENSORCLK                  (0x0020)
+#define CMU_LCDCLK                     (0x0024)
+#define CMU_DSICLK                     (0x0028)
+#define CMU_CSICLK                     (0x002C)
+#define CMU_DECLK                      (0x0030)
+#define CMU_BISPCLK                    (0x0034)
+#define CMU_BUSCLK1                    (0x0038)
+#define CMU_VDECLK                     (0x0040)
+#define CMU_VCECLK                     (0x0044)
+#define CMU_NANDCCLK                   (0x004C)
+#define CMU_SD0CLK                     (0x0050)
+#define CMU_SD1CLK                     (0x0054)
+#define CMU_SD2CLK                     (0x0058)
+#define CMU_UART0CLK                   (0x005C)
+#define CMU_UART1CLK                   (0x0060)
+#define CMU_UART2CLK                   (0x0064)
+#define CMU_PWM4CLK                    (0x0068)
+#define CMU_PWM5CLK                    (0x006C)
+#define CMU_PWM0CLK                    (0x0070)
+#define CMU_PWM1CLK                    (0x0074)
+#define CMU_PWM2CLK                    (0x0078)
+#define CMU_PWM3CLK                    (0x007C)
+#define CMU_USBPLL                     (0x0080)
+#define CMU_ETHERNETPLL                        (0x0084)
+#define CMU_CVBSPLL                    (0x0088)
+#define CMU_LENSCLK                    (0x008C)
+#define CMU_GPU3DCLK                   (0x0090)
+#define CMU_CORECTL                    (0x009C)
+#define CMU_DEVCLKEN0                  (0x00A0)
+#define CMU_DEVCLKEN1                  (0x00A4)
+#define CMU_DEVRST0                    (0x00A8)
+#define CMU_DEVRST1                    (0x00AC)
+#define CMU_UART3CLK                   (0x00B0)
+#define CMU_UART4CLK                   (0x00B4)
+#define CMU_UART5CLK                   (0x00B8)
+#define CMU_UART6CLK                   (0x00BC)
+#define CMU_SSCLK                      (0x00C0)
+#define CMU_DIGITALDEBUG               (0x00D0)
+#define CMU_ANALOGDEBUG                        (0x00D4)
+#define CMU_COREPLLDEBUG               (0x00D8)
+#define CMU_DEVPLLDEBUG                        (0x00DC)
+#define CMU_DDRPLLDEBUG                        (0x00E0)
+#define CMU_NANDPLLDEBUG               (0x00E4)
+#define CMU_DISPLAYPLLDEBUG            (0x00E8)
+#define CMU_TVOUTPLLDEBUG              (0x00EC)
+#define CMU_DEEPCOLORPLLDEBUG          (0x00F4)
+#define CMU_AUDIOPLL_ETHPLLDEBUG       (0x00F8)
+#define CMU_CVBSPLLDEBUG               (0x00FC)
+
+#define OWL_S500_COREPLL_DELAY         (150)
+#define OWL_S500_DDRPLL_DELAY          (63)
+#define OWL_S500_DEVPLL_DELAY          (28)
+#define OWL_S500_NANDPLL_DELAY         (44)
+#define OWL_S500_DISPLAYPLL_DELAY      (57)
+#define OWL_S500_ETHERNETPLL_DELAY     (25)
+#define OWL_S500_AUDIOPLL_DELAY                (100)
+
+static const struct clk_pll_table clk_audio_pll_table[] = {
+       { 0, 45158400 }, { 1, 49152000 },
+       { 0, 0 },
+};
+
+/* pll clocks */
+static OWL_PLL_NO_PARENT_DELAY(ethernet_pll_clk, "ethernet_pll_clk", CMU_ETHERNETPLL, 500000000, 0, 0, 0, 0, 0, OWL_S500_ETHERNETPLL_DELAY, NULL, CLK_IGNORE_UNUSED);
+static OWL_PLL_NO_PARENT_DELAY(core_pll_clk, "core_pll_clk", CMU_COREPLL, 12000000, 9, 0, 8, 4, 134, OWL_S500_COREPLL_DELAY, NULL, CLK_IGNORE_UNUSED);
+static OWL_PLL_NO_PARENT_DELAY(ddr_pll_clk, "ddr_pll_clk", CMU_DDRPLL, 12000000, 8, 0, 8, 1, 67, OWL_S500_DDRPLL_DELAY, NULL, CLK_IGNORE_UNUSED);
+static OWL_PLL_NO_PARENT_DELAY(nand_pll_clk, "nand_pll_clk", CMU_NANDPLL, 6000000, 8, 0, 7, 2, 86, OWL_S500_NANDPLL_DELAY, NULL, CLK_IGNORE_UNUSED);
+static OWL_PLL_NO_PARENT_DELAY(display_pll_clk, "display_pll_clk", CMU_DISPLAYPLL, 6000000, 8, 0, 8, 2, 126, OWL_S500_DISPLAYPLL_DELAY, NULL, CLK_IGNORE_UNUSED);
+static OWL_PLL_NO_PARENT_DELAY(dev_pll_clk, "dev_pll_clk", CMU_DEVPLL, 6000000, 8, 0, 7, 8, 126, OWL_S500_DEVPLL_DELAY, NULL, CLK_IGNORE_UNUSED);
+static OWL_PLL_NO_PARENT_DELAY(audio_pll_clk, "audio_pll_clk", CMU_AUDIOPLL, 0, 4, 0, 1, 0, 0, OWL_S500_AUDIOPLL_DELAY, clk_audio_pll_table, CLK_IGNORE_UNUSED);
+
+static const char * const dev_clk_mux_p[] = { "hosc", "dev_pll_clk" };
+static const char * const bisp_clk_mux_p[] = { "display_pll_clk", "dev_clk" };
+static const char * const sensor_clk_mux_p[] = { "hosc", "bisp_clk" };
+static const char * const sd_clk_mux_p[] = { "dev_clk", "nand_pll_clk" };
+static const char * const pwm_clk_mux_p[] = { "losc", "hosc" };
+static const char * const ahbprediv_clk_mux_p[] = { "dev_clk", "display_pll_clk", "nand_pll_clk", "ddr_pll_clk" };
+static const char * const uart_clk_mux_p[] = { "hosc", "dev_pll_clk" };
+static const char * const de_clk_mux_p[] = { "display_pll_clk", "dev_clk" };
+static const char * const i2s_clk_mux_p[] = { "audio_pll_clk" };
+static const char * const hde_clk_mux_p[] = { "dev_clk", "display_pll_clk", "nand_pll_clk", "ddr_pll_clk" };
+static const char * const nand_clk_mux_p[] = { "nand_pll_clk", "display_pll_clk", "dev_clk", "ddr_pll_clk" };
+
+static struct clk_factor_table sd_factor_table[] = {
+       /* bit0 ~ 4 */
+       { 0, 1, 1 }, { 1, 1, 2 }, { 2, 1, 3 }, { 3, 1, 4 },
+       { 4, 1, 5 }, { 5, 1, 6 }, { 6, 1, 7 }, { 7, 1, 8 },
+       { 8, 1, 9 }, { 9, 1, 10 }, { 10, 1, 11 }, { 11, 1, 12 },
+       { 12, 1, 13 }, { 13, 1, 14 }, { 14, 1, 15 }, { 15, 1, 16 },
+       { 16, 1, 17 }, { 17, 1, 18 }, { 18, 1, 19 }, { 19, 1, 20 },
+       { 20, 1, 21 }, { 21, 1, 22 }, { 22, 1, 23 }, { 23, 1, 24 },
+       { 24, 1, 25 }, { 25, 1, 26 }, { 26, 1, 27 }, { 27, 1, 28 },
+       { 28, 1, 29 }, { 29, 1, 30 }, { 30, 1, 31 }, { 31, 1, 32 },
+
+       /* bit8: /128 */
+       { 256, 1, 1 * 128 }, { 257, 1, 2 * 128 }, { 258, 1, 3 * 128 }, { 259, 1, 4 * 128 },
+       { 260, 1, 5 * 128 }, { 261, 1, 6 * 128 }, { 262, 1, 7 * 128 }, { 263, 1, 8 * 128 },
+       { 264, 1, 9 * 128 }, { 265, 1, 10 * 128 }, { 266, 1, 11 * 128 }, { 267, 1, 12 * 128 },
+       { 268, 1, 13 * 128 }, { 269, 1, 14 * 128 }, { 270, 1, 15 * 128 }, { 271, 1, 16 * 128 },
+       { 272, 1, 17 * 128 }, { 273, 1, 18 * 128 }, { 274, 1, 19 * 128 }, { 275, 1, 20 * 128 },
+       { 276, 1, 21 * 128 }, { 277, 1, 22 * 128 }, { 278, 1, 23 * 128 }, { 279, 1, 24 * 128 },
+       { 280, 1, 25 * 128 }, { 281, 1, 26 * 128 }, { 282, 1, 27 * 128 }, { 283, 1, 28 * 128 },
+       { 284, 1, 29 * 128 }, { 285, 1, 30 * 128 }, { 286, 1, 31 * 128 }, { 287, 1, 32 * 128 },
+       { 0, 0, 0 },
+};
+
+static struct clk_factor_table bisp_factor_table[] = {
+       { 0, 1, 1 }, { 1, 1, 2 }, { 2, 1, 3 }, { 3, 1, 4 },
+       { 4, 1, 5 }, { 5, 1, 6 }, { 6, 1, 7 }, { 7, 1, 8 },
+       { 0, 0, 0 },
+};
+
+static struct clk_factor_table ahb_factor_table[] = {
+       { 1, 1, 2 }, { 2, 1, 3 },
+       { 0, 0, 0 },
+};
+
+static struct clk_div_table rmii_ref_div_table[] = {
+       { 0, 4 }, { 1, 10 },
+       { 0, 0 },
+};
+
+static struct clk_div_table i2s_div_table[] = {
+       { 0, 1 }, { 1, 2 }, { 2, 3 }, { 3, 4 },
+       { 4, 6 }, { 5, 8 }, { 6, 12 }, { 7, 16 },
+       { 8, 24 },
+       { 0, 0 },
+};
+
+static struct clk_div_table nand_div_table[] = {
+       { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 6 },
+       { 4, 8 }, { 5, 10 }, { 6, 12 }, { 7, 14 },
+       { 8, 16 }, { 9, 18 }, { 10, 20 }, { 11, 22 },
+       { 0, 0 },
+};
+
+/* mux clock */
+static OWL_MUX(dev_clk, "dev_clk", dev_clk_mux_p, CMU_DEVPLL, 12, 1, CLK_SET_RATE_PARENT);
+static OWL_MUX(ahbprediv_clk, "ahbprediv_clk", ahbprediv_clk_mux_p, CMU_BUSCLK1, 8, 3, CLK_SET_RATE_PARENT);
+
+/* gate clocks */
+static OWL_GATE(spi0_clk, "spi0_clk", "ahb_clk", CMU_DEVCLKEN1, 10, 0, CLK_IGNORE_UNUSED);
+static OWL_GATE(spi1_clk, "spi1_clk", "ahb_clk", CMU_DEVCLKEN1, 11, 0, CLK_IGNORE_UNUSED);
+static OWL_GATE(spi2_clk, "spi2_clk", "ahb_clk", CMU_DEVCLKEN1, 12, 0, CLK_IGNORE_UNUSED);
+static OWL_GATE(spi3_clk, "spi3_clk", "ahb_clk", CMU_DEVCLKEN1, 13, 0, CLK_IGNORE_UNUSED);
+static OWL_GATE(timer_clk, "timer_clk", "hosc", CMU_DEVCLKEN1, 27, 0, 0);
+static OWL_GATE(hdmi_clk, "hdmi_clk", "hosc", CMU_DEVCLKEN1, 3, 0, 0);
+
+/* divider clocks */
+static OWL_DIVIDER(h_clk, "h_clk", "ahbprevdiv_clk", CMU_BUSCLK1, 12, 2, NULL, 0, 0);
+static OWL_DIVIDER(rmii_ref_clk, "rmii_ref_clk", "ethernet_pll_clk", CMU_ETHERNETPLL, 1, 1, rmii_ref_div_table, 0, 0);
+
+/* factor clocks */
+static OWL_FACTOR(ahb_clk, "ahb_clk", "h_clk", CMU_BUSCLK1, 2, 2, ahb_factor_table, 0, 0);
+static OWL_FACTOR(de1_clk, "de_clk1", "de_clk", CMU_DECLK, 0, 3, bisp_factor_table, 0, 0);
+static OWL_FACTOR(de2_clk, "de_clk2", "de_clk", CMU_DECLK, 4, 3, bisp_factor_table, 0, 0);
+
+/* composite clocks */
+static OWL_COMP_FACTOR(vce_clk, "vce_clk", hde_clk_mux_p,
+                       OWL_MUX_HW(CMU_VCECLK, 4, 2),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 26, 0),
+                       OWL_FACTOR_HW(CMU_VCECLK, 0, 3, 0, bisp_factor_table),
+                       0);
+
+static OWL_COMP_FACTOR(vde_clk, "vde_clk", hde_clk_mux_p,
+                       OWL_MUX_HW(CMU_VDECLK, 4, 2),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 25, 0),
+                       OWL_FACTOR_HW(CMU_VDECLK, 0, 3, 0, bisp_factor_table),
+                       0);
+
+static OWL_COMP_FACTOR(bisp_clk, "bisp_clk", bisp_clk_mux_p,
+                       OWL_MUX_HW(CMU_BISPCLK, 4, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0),
+                       OWL_FACTOR_HW(CMU_BISPCLK, 0, 3, 0, bisp_factor_table),
+                       0);
+
+static OWL_COMP_FACTOR(sensor0_clk, "sensor0_clk", sensor_clk_mux_p,
+                       OWL_MUX_HW(CMU_SENSORCLK, 4, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0),
+                       OWL_FACTOR_HW(CMU_SENSORCLK, 0, 3, 0, bisp_factor_table),
+                       CLK_IGNORE_UNUSED);
+
+static OWL_COMP_FACTOR(sensor1_clk, "sensor1_clk", sensor_clk_mux_p,
+                       OWL_MUX_HW(CMU_SENSORCLK, 4, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 14, 0),
+                       OWL_FACTOR_HW(CMU_SENSORCLK, 8, 3, 0, bisp_factor_table),
+                       CLK_IGNORE_UNUSED);
+
+static OWL_COMP_FACTOR(sd0_clk, "sd0_clk", sd_clk_mux_p,
+                       OWL_MUX_HW(CMU_SD0CLK, 9, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 5, 0),
+                       OWL_FACTOR_HW(CMU_SD0CLK, 0, 9, 0, sd_factor_table),
+                       0);
+
+static OWL_COMP_FACTOR(sd1_clk, "sd1_clk", sd_clk_mux_p,
+                       OWL_MUX_HW(CMU_SD1CLK, 9, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 6, 0),
+                       OWL_FACTOR_HW(CMU_SD1CLK, 0, 9, 0, sd_factor_table),
+                       0);
+
+static OWL_COMP_FACTOR(sd2_clk, "sd2_clk", sd_clk_mux_p,
+                       OWL_MUX_HW(CMU_SD2CLK, 9, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 7, 0),
+                       OWL_FACTOR_HW(CMU_SD2CLK, 0, 9, 0, sd_factor_table),
+                       0);
+
+static OWL_COMP_DIV(pwm0_clk, "pwm0_clk", pwm_clk_mux_p,
+                       OWL_MUX_HW(CMU_PWM0CLK, 12, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN1, 23, 0),
+                       OWL_DIVIDER_HW(CMU_PWM0CLK, 0, 10, 0, NULL),
+                       0);
+
+static OWL_COMP_DIV(pwm1_clk, "pwm1_clk", pwm_clk_mux_p,
+                       OWL_MUX_HW(CMU_PWM1CLK, 12, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN1, 24, 0),
+                       OWL_DIVIDER_HW(CMU_PWM1CLK, 0, 10, 0, NULL),
+                       0);
+
+static OWL_COMP_DIV(pwm2_clk, "pwm2_clk", pwm_clk_mux_p,
+                       OWL_MUX_HW(CMU_PWM2CLK, 12, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN1, 25, 0),
+                       OWL_DIVIDER_HW(CMU_PWM2CLK, 0, 10, 0, NULL),
+                       0);
+
+static OWL_COMP_DIV(pwm3_clk, "pwm3_clk", pwm_clk_mux_p,
+                       OWL_MUX_HW(CMU_PWM3CLK, 12, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN1, 26, 0),
+                       OWL_DIVIDER_HW(CMU_PWM3CLK, 0, 10, 0, NULL),
+                       0);
+
+static OWL_COMP_DIV(pwm4_clk, "pwm4_clk", pwm_clk_mux_p,
+                       OWL_MUX_HW(CMU_PWM4CLK, 12, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 11, 0),
+                       OWL_DIVIDER_HW(CMU_PWM4CLK, 0, 10, 0, NULL),
+                       0);
+
+static OWL_COMP_DIV(pwm5_clk, "pwm5_clk", pwm_clk_mux_p,
+                       OWL_MUX_HW(CMU_PWM5CLK, 12, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 0, 0),
+                       OWL_DIVIDER_HW(CMU_PWM5CLK, 0, 10, 0, NULL),
+                       0);
+
+static OWL_COMP_PASS(de_clk, "de_clk", de_clk_mux_p,
+                       OWL_MUX_HW(CMU_DECLK, 12, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 8, 0),
+                       0);
+
+static OWL_COMP_FIXED_FACTOR(i2c0_clk, "i2c0_clk", "ethernet_pll_clk",
+                       OWL_GATE_HW(CMU_DEVCLKEN1, 14, 0),
+                       1, 5, 0);
+
+static OWL_COMP_FIXED_FACTOR(i2c1_clk, "i2c1_clk", "ethernet_pll_clk",
+                       OWL_GATE_HW(CMU_DEVCLKEN1, 15, 0),
+                       1, 5, 0);
+
+static OWL_COMP_FIXED_FACTOR(i2c2_clk, "i2c2_clk", "ethernet_pll_clk",
+                       OWL_GATE_HW(CMU_DEVCLKEN1, 30, 0),
+                       1, 5, 0);
+
+static OWL_COMP_FIXED_FACTOR(i2c3_clk, "i2c3_clk", "ethernet_pll_clk",
+                       OWL_GATE_HW(CMU_DEVCLKEN1, 31, 0),
+                       1, 5, 0);
+
+static OWL_COMP_DIV(uart0_clk, "uart0_clk", uart_clk_mux_p,
+                       OWL_MUX_HW(CMU_UART0CLK, 16, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN1, 6, 0),
+                       OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
+                       CLK_IGNORE_UNUSED);
+
+static OWL_COMP_DIV(uart1_clk, "uart1_clk", uart_clk_mux_p,
+                       OWL_MUX_HW(CMU_UART1CLK, 16, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN1, 7, 0),
+                       OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
+                       CLK_IGNORE_UNUSED);
+
+static OWL_COMP_DIV(uart2_clk, "uart2_clk", uart_clk_mux_p,
+                       OWL_MUX_HW(CMU_UART2CLK, 16, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN1, 8, 0),
+                       OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
+                       CLK_IGNORE_UNUSED);
+
+static OWL_COMP_DIV(uart3_clk, "uart3_clk", uart_clk_mux_p,
+                       OWL_MUX_HW(CMU_UART3CLK, 16, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN1, 19, 0),
+                       OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
+                       CLK_IGNORE_UNUSED);
+
+static OWL_COMP_DIV(uart4_clk, "uart4_clk", uart_clk_mux_p,
+                       OWL_MUX_HW(CMU_UART4CLK, 16, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN1, 20, 0),
+                       OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
+                       CLK_IGNORE_UNUSED);
+
+static OWL_COMP_DIV(uart5_clk, "uart5_clk", uart_clk_mux_p,
+                       OWL_MUX_HW(CMU_UART5CLK, 16, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN1, 21, 0),
+                       OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
+                       CLK_IGNORE_UNUSED);
+
+static OWL_COMP_DIV(uart6_clk, "uart6_clk", uart_clk_mux_p,
+                       OWL_MUX_HW(CMU_UART6CLK, 16, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN1, 18, 0),
+                       OWL_DIVIDER_HW(CMU_UART1CLK, 0, 8, CLK_DIVIDER_ROUND_CLOSEST, NULL),
+                       CLK_IGNORE_UNUSED);
+
+static OWL_COMP_DIV(i2srx_clk, "i2srx_clk", i2s_clk_mux_p,
+                       OWL_MUX_HW(CMU_AUDIOPLL, 24, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 21, 0),
+                       OWL_DIVIDER_HW(CMU_AUDIOPLL, 20, 4, 0, i2s_div_table),
+                       0);
+
+static OWL_COMP_DIV(i2stx_clk, "i2stx_clk", i2s_clk_mux_p,
+                       OWL_MUX_HW(CMU_AUDIOPLL, 24, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 20, 0),
+                       OWL_DIVIDER_HW(CMU_AUDIOPLL, 16, 4, 0, i2s_div_table),
+                       0);
+
+static OWL_COMP_DIV(hdmia_clk, "hdmia_clk", i2s_clk_mux_p,
+                       OWL_MUX_HW(CMU_AUDIOPLL, 24, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 22, 0),
+                       OWL_DIVIDER_HW(CMU_AUDIOPLL, 24, 4, 0, i2s_div_table),
+                       0);
+
+static OWL_COMP_DIV(spdif_clk, "spdif_clk", i2s_clk_mux_p,
+                       OWL_MUX_HW(CMU_AUDIOPLL, 24, 1),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 23, 0),
+                       OWL_DIVIDER_HW(CMU_AUDIOPLL, 28, 4, 0, i2s_div_table),
+                       0);
+
+static OWL_COMP_DIV(nand_clk, "nand_clk", nand_clk_mux_p,
+                       OWL_MUX_HW(CMU_NANDCCLK, 8, 2),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 4, 0),
+                       OWL_DIVIDER_HW(CMU_NANDCCLK, 0, 3, 0, nand_div_table),
+                       CLK_SET_RATE_PARENT);
+
+static OWL_COMP_DIV(ecc_clk, "ecc_clk", nand_clk_mux_p,
+                       OWL_MUX_HW(CMU_NANDCCLK, 8, 2),
+                       OWL_GATE_HW(CMU_DEVCLKEN0, 4, 0),
+                       OWL_DIVIDER_HW(CMU_NANDCCLK, 4, 3, 0, nand_div_table),
+                       CLK_SET_RATE_PARENT);
+
+static struct owl_clk_common *s500_clks[] = {
+       &ethernet_pll_clk.common,
+       &core_pll_clk.common,
+       &ddr_pll_clk.common,
+       &dev_pll_clk.common,
+       &nand_pll_clk.common,
+       &audio_pll_clk.common,
+       &display_pll_clk.common,
+       &dev_clk.common,
+       &timer_clk.common,
+       &i2c0_clk.common,
+       &i2c1_clk.common,
+       &i2c2_clk.common,
+       &i2c3_clk.common,
+       &uart0_clk.common,
+       &uart1_clk.common,
+       &uart2_clk.common,
+       &uart3_clk.common,
+       &uart4_clk.common,
+       &uart5_clk.common,
+       &uart6_clk.common,
+       &pwm0_clk.common,
+       &pwm1_clk.common,
+       &pwm2_clk.common,
+       &pwm3_clk.common,
+       &pwm4_clk.common,
+       &pwm5_clk.common,
+       &sensor0_clk.common,
+       &sensor1_clk.common,
+       &sd0_clk.common,
+       &sd1_clk.common,
+       &sd2_clk.common,
+       &bisp_clk.common,
+       &ahb_clk.common,
+       &ahbprediv_clk.common,
+       &h_clk.common,
+       &spi0_clk.common,
+       &spi1_clk.common,
+       &spi2_clk.common,
+       &spi3_clk.common,
+       &rmii_ref_clk.common,
+       &de_clk.common,
+       &de1_clk.common,
+       &de2_clk.common,
+       &i2srx_clk.common,
+       &i2stx_clk.common,
+       &hdmia_clk.common,
+       &hdmi_clk.common,
+       &vce_clk.common,
+       &vde_clk.common,
+       &spdif_clk.common,
+       &nand_clk.common,
+       &ecc_clk.common,
+};
+
+static struct clk_hw_onecell_data s500_hw_clks = {
+       .hws = {
+               [CLK_ETHERNET_PLL]      = &ethernet_pll_clk.common.hw,
+               [CLK_CORE_PLL]          = &core_pll_clk.common.hw,
+               [CLK_DDR_PLL]           = &ddr_pll_clk.common.hw,
+               [CLK_NAND_PLL]          = &nand_pll_clk.common.hw,
+               [CLK_DISPLAY_PLL]       = &display_pll_clk.common.hw,
+               [CLK_DEV_PLL]           = &dev_pll_clk.common.hw,
+               [CLK_AUDIO_PLL]         = &audio_pll_clk.common.hw,
+               [CLK_TIMER]             = &timer_clk.common.hw,
+               [CLK_DEV]               = &dev_clk.common.hw,
+               [CLK_DE]                = &de_clk.common.hw,
+               [CLK_DE1]               = &de1_clk.common.hw,
+               [CLK_DE2]               = &de2_clk.common.hw,
+               [CLK_I2C0]              = &i2c0_clk.common.hw,
+               [CLK_I2C1]              = &i2c1_clk.common.hw,
+               [CLK_I2C2]              = &i2c2_clk.common.hw,
+               [CLK_I2C3]              = &i2c3_clk.common.hw,
+               [CLK_I2SRX]             = &i2srx_clk.common.hw,
+               [CLK_I2STX]             = &i2stx_clk.common.hw,
+               [CLK_UART0]             = &uart0_clk.common.hw,
+               [CLK_UART1]             = &uart1_clk.common.hw,
+               [CLK_UART2]             = &uart2_clk.common.hw,
+               [CLK_UART3]             = &uart3_clk.common.hw,
+               [CLK_UART4]             = &uart4_clk.common.hw,
+               [CLK_UART5]             = &uart5_clk.common.hw,
+               [CLK_UART6]             = &uart6_clk.common.hw,
+               [CLK_PWM0]              = &pwm0_clk.common.hw,
+               [CLK_PWM1]              = &pwm1_clk.common.hw,
+               [CLK_PWM2]              = &pwm2_clk.common.hw,
+               [CLK_PWM3]              = &pwm3_clk.common.hw,
+               [CLK_PWM4]              = &pwm4_clk.common.hw,
+               [CLK_PWM5]              = &pwm5_clk.common.hw,
+               [CLK_SENSOR0]           = &sensor0_clk.common.hw,
+               [CLK_SENSOR1]           = &sensor1_clk.common.hw,
+               [CLK_SD0]               = &sd0_clk.common.hw,
+               [CLK_SD1]               = &sd1_clk.common.hw,
+               [CLK_SD2]               = &sd2_clk.common.hw,
+               [CLK_BISP]              = &bisp_clk.common.hw,
+               [CLK_SPI0]              = &spi0_clk.common.hw,
+               [CLK_SPI1]              = &spi1_clk.common.hw,
+               [CLK_SPI2]              = &spi2_clk.common.hw,
+               [CLK_SPI3]              = &spi3_clk.common.hw,
+               [CLK_AHB]               = &ahb_clk.common.hw,
+               [CLK_H]                 = &h_clk.common.hw,
+               [CLK_AHBPREDIV]         = &ahbprediv_clk.common.hw,
+               [CLK_RMII_REF]          = &rmii_ref_clk.common.hw,
+               [CLK_HDMI_AUDIO]        = &hdmia_clk.common.hw,
+               [CLK_HDMI]              = &hdmi_clk.common.hw,
+               [CLK_VDE]               = &vde_clk.common.hw,
+               [CLK_VCE]               = &vce_clk.common.hw,
+               [CLK_SPDIF]             = &spdif_clk.common.hw,
+               [CLK_NAND]              = &nand_clk.common.hw,
+               [CLK_ECC]               = &ecc_clk.common.hw,
+       },
+       .num = CLK_NR_CLKS,
+};
+
+static struct owl_clk_desc s500_clk_desc = {
+       .clks       = s500_clks,
+       .num_clks   = ARRAY_SIZE(s500_clks),
+
+       .hw_clks    = &s500_hw_clks,
+};
+
+static int s500_clk_probe(struct platform_device *pdev)
+{
+       struct owl_clk_desc *desc;
+
+       desc = &s500_clk_desc;
+       owl_clk_regmap_init(pdev, desc);
+
+       return owl_clk_probe(&pdev->dev, desc->hw_clks);
+}
+
+static const struct of_device_id s500_clk_of_match[] = {
+       { .compatible = "actions,s500-cmu", },
+       { /* sentinel */ }
+};
+
+static struct platform_driver s500_clk_driver = {
+       .probe = s500_clk_probe,
+       .driver = {
+               .name = "s500-cmu",
+               .of_match_table = s500_clk_of_match,
+       },
+};
+
+static int __init s500_clk_init(void)
+{
+       return platform_driver_register(&s500_clk_driver);
+}
+core_initcall(s500_clk_init);
index 2fe225a..3487e03 100644 (file)
@@ -144,8 +144,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
                return;
 
        at91sam9x5_pmc = pmc_data_allocate(PMC_MAIN + 1,
-                                          nck(at91sam9x5_systemck),
-                                          nck(at91sam9x35_periphck), 0);
+                                          nck(at91sam9x5_systemck), 31, 0);
        if (!at91sam9x5_pmc)
                return;
 
@@ -210,7 +209,7 @@ static void __init at91sam9x5_pmc_setup(struct device_node *np,
        parent_names[1] = "mainck";
        parent_names[2] = "plladivck";
        parent_names[3] = "utmick";
-       parent_names[4] = "mck";
+       parent_names[4] = "masterck";
        for (i = 0; i < 2; i++) {
                char name[6];
 
index d69ad96..cd0ef72 100644 (file)
@@ -240,7 +240,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
        parent_names[1] = "mainck";
        parent_names[2] = "plladivck";
        parent_names[3] = "utmick";
-       parent_names[4] = "mck";
+       parent_names[4] = "masterck";
        for (i = 0; i < 3; i++) {
                char name[6];
 
@@ -291,7 +291,7 @@ static void __init sama5d2_pmc_setup(struct device_node *np)
        parent_names[1] = "mainck";
        parent_names[2] = "plladivck";
        parent_names[3] = "utmick";
-       parent_names[4] = "mck";
+       parent_names[4] = "masterck";
        parent_names[5] = "audiopll_pmcck";
        for (i = 0; i < ARRAY_SIZE(sama5d2_gck); i++) {
                hw = at91_clk_register_generated(regmap, &pmc_pcr_lock,
index e358be7..b645a9d 100644 (file)
@@ -207,7 +207,7 @@ static void __init sama5d4_pmc_setup(struct device_node *np)
        parent_names[1] = "mainck";
        parent_names[2] = "plladivck";
        parent_names[3] = "utmick";
-       parent_names[4] = "mck";
+       parent_names[4] = "masterck";
        for (i = 0; i < 3; i++) {
                char name[6];
 
index 2c04396..c36c47b 100644 (file)
@@ -44,21 +44,21 @@ struct clps711x_clk {
        struct clk_hw_onecell_data      clk_data;
 };
 
-static struct clps711x_clk * __init _clps711x_clk_init(void __iomem *base,
-                                                      u32 fref)
+static void __init clps711x_clk_init_dt(struct device_node *np)
 {
-       u32 tmp, f_cpu, f_pll, f_bus, f_tim, f_pwm, f_spi;
+       u32 tmp, f_cpu, f_pll, f_bus, f_tim, f_pwm, f_spi, fref = 0;
        struct clps711x_clk *clps711x_clk;
-       unsigned i;
+       void __iomem *base;
+
+       WARN_ON(of_property_read_u32(np, "startup-frequency", &fref));
 
-       if (!base)
-               return ERR_PTR(-ENOMEM);
+       base = of_iomap(np, 0);
+       BUG_ON(!base);
 
        clps711x_clk = kzalloc(struct_size(clps711x_clk, clk_data.hws,
                                           CLPS711X_CLK_MAX),
                               GFP_KERNEL);
-       if (!clps711x_clk)
-               return ERR_PTR(-ENOMEM);
+       BUG_ON(!clps711x_clk);
 
        spin_lock_init(&clps711x_clk->lock);
 
@@ -137,52 +137,13 @@ static struct clps711x_clk * __init _clps711x_clk_init(void __iomem *base,
                clk_hw_register_fixed_factor(NULL, "uart", "bus", 0, 1, 10);
        clps711x_clk->clk_data.hws[CLPS711X_CLK_TICK] =
                clk_hw_register_fixed_rate(NULL, "tick", NULL, 0, 64);
-       for (i = 0; i < CLPS711X_CLK_MAX; i++)
-               if (IS_ERR(clps711x_clk->clk_data.hws[i]))
+       for (tmp = 0; tmp < CLPS711X_CLK_MAX; tmp++)
+               if (IS_ERR(clps711x_clk->clk_data.hws[tmp]))
                        pr_err("clk %i: register failed with %ld\n",
-                              i, PTR_ERR(clps711x_clk->clk_data.hws[i]));
-
-       return clps711x_clk;
-}
-
-void __init clps711x_clk_init(void __iomem *base)
-{
-       struct clps711x_clk *clps711x_clk;
-
-       clps711x_clk = _clps711x_clk_init(base, 73728000);
-
-       BUG_ON(IS_ERR(clps711x_clk));
-
-       /* Clocksource */
-       clk_hw_register_clkdev(clps711x_clk->clk_data.hws[CLPS711X_CLK_TIMER1],
-                           NULL, "clps711x-timer.0");
-       clk_hw_register_clkdev(clps711x_clk->clk_data.hws[CLPS711X_CLK_TIMER2],
-                           NULL, "clps711x-timer.1");
-
-       /* Drivers */
-       clk_hw_register_clkdev(clps711x_clk->clk_data.hws[CLPS711X_CLK_PWM],
-                           NULL, "clps711x-pwm");
-       clk_hw_register_clkdev(clps711x_clk->clk_data.hws[CLPS711X_CLK_UART],
-                           NULL, "clps711x-uart.0");
-       clk_hw_register_clkdev(clps711x_clk->clk_data.hws[CLPS711X_CLK_UART],
-                           NULL, "clps711x-uart.1");
-}
-
-#ifdef CONFIG_OF
-static void __init clps711x_clk_init_dt(struct device_node *np)
-{
-       void __iomem *base = of_iomap(np, 0);
-       struct clps711x_clk *clps711x_clk;
-       u32 fref = 0;
-
-       WARN_ON(of_property_read_u32(np, "startup-frequency", &fref));
-
-       clps711x_clk = _clps711x_clk_init(base, fref);
-       BUG_ON(IS_ERR(clps711x_clk));
+                              tmp, PTR_ERR(clps711x_clk->clk_data.hws[tmp]));
 
        clps711x_clk->clk_data.num = CLPS711X_CLK_MAX;
        of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
                               &clps711x_clk->clk_data);
 }
 CLK_OF_DECLARE(clps711x, "cirrus,ep7209-clk", clps711x_clk_init_dt);
-#endif
index c9a8615..daa1fc8 100644 (file)
@@ -29,6 +29,17 @@ struct clk *devm_clk_get(struct device *dev, const char *id)
 }
 EXPORT_SYMBOL(devm_clk_get);
 
+struct clk *devm_clk_get_optional(struct device *dev, const char *id)
+{
+       struct clk *clk = devm_clk_get(dev, id);
+
+       if (clk == ERR_PTR(-ENOENT))
+               return NULL;
+
+       return clk;
+}
+EXPORT_SYMBOL(devm_clk_get_optional);
+
 struct clk_bulk_devres {
        struct clk_bulk_data *clks;
        int num_clks;
diff --git a/drivers/clk/clk-fixed-mmio.c b/drivers/clk/clk-fixed-mmio.c
new file mode 100644 (file)
index 0000000..d1a97d9
--- /dev/null
@@ -0,0 +1,101 @@
+// SPDX-License-Identifier: GPL-2.0
+
+/*
+ * Memory Mapped IO Fixed clock driver
+ *
+ * Copyright (C) 2018 Cadence Design Systems, Inc.
+ *
+ * Authors:
+ *     Jan Kotas <jank@cadence.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of_address.h>
+#include <linux/module.h>
+#include <linux/platform_device.h>
+
+static struct clk_hw *fixed_mmio_clk_setup(struct device_node *node)
+{
+       struct clk_hw *clk;
+       const char *clk_name = node->name;
+       void __iomem *base;
+       u32 freq;
+       int ret;
+
+       base = of_iomap(node, 0);
+       if (!base) {
+               pr_err("%pOFn: failed to map address\n", node);
+               return ERR_PTR(-EIO);
+       }
+
+       freq = readl(base);
+       iounmap(base);
+       of_property_read_string(node, "clock-output-names", &clk_name);
+
+       clk = clk_hw_register_fixed_rate(NULL, clk_name, NULL, 0, freq);
+       if (IS_ERR(clk)) {
+               pr_err("%pOFn: failed to register fixed rate clock\n", node);
+               return clk;
+       }
+
+       ret = of_clk_add_hw_provider(node, of_clk_hw_simple_get, clk);
+       if (ret) {
+               pr_err("%pOFn: failed to add clock provider\n", node);
+               clk_hw_unregister(clk);
+               clk = ERR_PTR(ret);
+       }
+
+       return clk;
+}
+
+static void __init of_fixed_mmio_clk_setup(struct device_node *node)
+{
+       fixed_mmio_clk_setup(node);
+}
+CLK_OF_DECLARE(fixed_mmio_clk, "fixed-mmio-clock", of_fixed_mmio_clk_setup);
+
+/**
+ * This is not executed when of_fixed_mmio_clk_setup succeeded.
+ */
+static int of_fixed_mmio_clk_probe(struct platform_device *pdev)
+{
+       struct clk_hw *clk;
+
+       clk = fixed_mmio_clk_setup(pdev->dev.of_node);
+       if (IS_ERR(clk))
+               return PTR_ERR(clk);
+
+       platform_set_drvdata(pdev, clk);
+
+       return 0;
+}
+
+static int of_fixed_mmio_clk_remove(struct platform_device *pdev)
+{
+       struct clk_hw *clk = platform_get_drvdata(pdev);
+
+       of_clk_del_provider(pdev->dev.of_node);
+       clk_hw_unregister_fixed_rate(clk);
+
+       return 0;
+}
+
+static const struct of_device_id of_fixed_mmio_clk_ids[] = {
+       { .compatible = "fixed-mmio-clock" },
+       { }
+};
+MODULE_DEVICE_TABLE(of, of_fixed_mmio_clk_ids);
+
+static struct platform_driver of_fixed_mmio_clk_driver = {
+       .driver = {
+               .name = "of_fixed_mmio_clk",
+               .of_match_table = of_fixed_mmio_clk_ids,
+       },
+       .probe = of_fixed_mmio_clk_probe,
+       .remove = of_fixed_mmio_clk_remove,
+};
+module_platform_driver(of_fixed_mmio_clk_driver);
+
+MODULE_AUTHOR("Jan Kotas <jank@cadence.com>");
+MODULE_DESCRIPTION("Memory Mapped IO Fixed clock driver");
+MODULE_LICENSE("GPL v2");
index 545dcee..fdfe2e4 100644 (file)
@@ -79,7 +79,7 @@ static long clk_fd_round_rate(struct clk_hw *hw, unsigned long rate,
        unsigned long m, n;
        u64 ret;
 
-       if (!rate || rate >= *parent_rate)
+       if (!rate || (!clk_hw_can_set_rate_parent(hw) && rate >= *parent_rate))
                return *parent_rate;
 
        if (fd->approximation)
index 25eed3e..c2f07f0 100644 (file)
@@ -58,6 +58,35 @@ const struct clk_ops clk_gpio_gate_ops = {
 };
 EXPORT_SYMBOL_GPL(clk_gpio_gate_ops);
 
+static int clk_sleeping_gpio_gate_prepare(struct clk_hw *hw)
+{
+       struct clk_gpio *clk = to_clk_gpio(hw);
+
+       gpiod_set_value_cansleep(clk->gpiod, 1);
+
+       return 0;
+}
+
+static void clk_sleeping_gpio_gate_unprepare(struct clk_hw *hw)
+{
+       struct clk_gpio *clk = to_clk_gpio(hw);
+
+       gpiod_set_value_cansleep(clk->gpiod, 0);
+}
+
+static int clk_sleeping_gpio_gate_is_prepared(struct clk_hw *hw)
+{
+       struct clk_gpio *clk = to_clk_gpio(hw);
+
+       return gpiod_get_value_cansleep(clk->gpiod);
+}
+
+static const struct clk_ops clk_sleeping_gpio_gate_ops = {
+       .prepare = clk_sleeping_gpio_gate_prepare,
+       .unprepare = clk_sleeping_gpio_gate_unprepare,
+       .is_prepared = clk_sleeping_gpio_gate_is_prepared,
+};
+
 /**
  * DOC: basic clock multiplexer which can be controlled with a gpio output
  * Traits of this clock:
@@ -144,10 +173,16 @@ struct clk_hw *clk_hw_register_gpio_gate(struct device *dev, const char *name,
                const char *parent_name, struct gpio_desc *gpiod,
                unsigned long flags)
 {
+       const struct clk_ops *ops;
+
+       if (gpiod_cansleep(gpiod))
+               ops = &clk_sleeping_gpio_gate_ops;
+       else
+               ops = &clk_gpio_gate_ops;
+
        return clk_register_gpio(dev, name,
                        (parent_name ? &parent_name : NULL),
-                       (parent_name ? 1 : 0), gpiod, flags,
-                       &clk_gpio_gate_ops);
+                       (parent_name ? 1 : 0), gpiod, flags, ops);
 }
 EXPORT_SYMBOL_GPL(clk_hw_register_gpio_gate);
 
index 727ed8e..8e45810 100644 (file)
@@ -293,6 +293,7 @@ static __init struct clk *hb_clk_init(struct device_node *node, const struct clk
        /* Map system registers */
        srnp = of_find_compatible_node(NULL, NULL, "calxeda,hb-sregs");
        hb_clk->reg = of_iomap(srnp, 0);
+       of_node_put(srnp);
        BUG_ON(!hb_clk->reg);
        hb_clk->reg += reg;
 
index 22c9376..3727d54 100644 (file)
@@ -235,8 +235,9 @@ static int max77686_clk_probe(struct platform_device *pdev)
                        return ret;
                }
 
-               ret = clk_hw_register_clkdev(&max_clk_data->hw,
-                                            max_clk_data->clk_idata.name, NULL);
+               ret = devm_clk_hw_register_clkdev(dev, &max_clk_data->hw,
+                                                 max_clk_data->clk_idata.name,
+                                                 NULL);
                if (ret < 0) {
                        dev_err(dev, "Failed to clkdev register: %d\n", ret);
                        return ret;
@@ -244,8 +245,8 @@ static int max77686_clk_probe(struct platform_device *pdev)
        }
 
        if (parent->of_node) {
-               ret = of_clk_add_hw_provider(parent->of_node, of_clk_max77686_get,
-                                            drv_data);
+               ret = devm_of_clk_add_hw_provider(dev, of_clk_max77686_get,
+                                                 drv_data);
 
                if (ret < 0) {
                        dev_err(dev, "Failed to register OF clock provider: %d\n",
@@ -261,27 +262,11 @@ static int max77686_clk_probe(struct platform_device *pdev)
                                         1 << MAX77802_CLOCK_LOW_JITTER_SHIFT);
                if (ret < 0) {
                        dev_err(dev, "Failed to config low-jitter: %d\n", ret);
-                       goto remove_of_clk_provider;
+                       return ret;
                }
        }
 
        return 0;
-
-remove_of_clk_provider:
-       if (parent->of_node)
-               of_clk_del_provider(parent->of_node);
-
-       return ret;
-}
-
-static int max77686_clk_remove(struct platform_device *pdev)
-{
-       struct device *parent = pdev->dev.parent;
-
-       if (parent->of_node)
-               of_clk_del_provider(parent->of_node);
-
-       return 0;
 }
 
 static const struct platform_device_id max77686_clk_id[] = {
@@ -297,7 +282,6 @@ static struct platform_driver max77686_clk_driver = {
                .name  = "max77686-clk",
        },
        .probe = max77686_clk_probe,
-       .remove = max77686_clk_remove,
        .id_table = max77686_clk_id,
 };
 
index 5baa9e0..1212a9b 100644 (file)
@@ -1148,8 +1148,8 @@ static void __init create_one_pll(struct clockgen *cg, int idx)
                pll->div[i].clk = clk;
                ret = clk_register_clkdev(clk, pll->div[i].name, NULL);
                if (ret != 0)
-                       pr_err("%s: %s: register to lookup table failed %ld\n",
-                              __func__, pll->div[i].name, PTR_ERR(clk));
+                       pr_err("%s: %s: register to lookup table failed %d\n",
+                              __func__, pll->div[i].name, ret);
 
        }
 }
@@ -1389,6 +1389,7 @@ static void __init clockgen_init(struct device_node *np)
                                pr_err("%s: Couldn't map %pOF regs\n", __func__,
                                       guts);
                        }
+                       of_node_put(guts);
                }
 
        }
index 6a31f7f..a0ae8dc 100644 (file)
@@ -121,7 +121,7 @@ static const char * const cpu_src[] = {
 };
 
 static const char * const axi_src[] = {
-       "ck_hsi", "ck_hse", "pll2_p", "pll3_p"
+       "ck_hsi", "ck_hse", "pll2_p"
 };
 
 static const char * const per_src[] = {
@@ -225,19 +225,19 @@ static const char * const usart6_src[] = {
 };
 
 static const char * const fdcan_src[] = {
-       "ck_hse", "pll3_q", "pll4_q"
+       "ck_hse", "pll3_q", "pll4_q", "pll4_r"
 };
 
 static const char * const sai_src[] = {
-       "pll4_q", "pll3_q", "i2s_ckin", "ck_per"
+       "pll4_q", "pll3_q", "i2s_ckin", "ck_per", "pll3_r"
 };
 
 static const char * const sai2_src[] = {
-       "pll4_q", "pll3_q", "i2s_ckin", "ck_per", "spdif_ck_symb"
+       "pll4_q", "pll3_q", "i2s_ckin", "ck_per", "spdif_ck_symb", "pll3_r"
 };
 
 static const char * const adc12_src[] = {
-       "pll4_q", "ck_per"
+       "pll4_r", "ck_per", "pll3_q"
 };
 
 static const char * const dsi_src[] = {
@@ -269,7 +269,7 @@ static const struct clk_div_table axi_div_table[] = {
 static const struct clk_div_table mcu_div_table[] = {
        { 0, 1 }, { 1, 2 }, { 2, 4 }, { 3, 8 },
        { 4, 16 }, { 5, 32 }, { 6, 64 }, { 7, 128 },
-       { 8, 512 }, { 9, 512 }, { 10, 512}, { 11, 512 },
+       { 8, 256 }, { 9, 512 }, { 10, 512}, { 11, 512 },
        { 12, 512 }, { 13, 512 }, { 14, 512}, { 15, 512 },
        { 0 },
 };
@@ -1286,10 +1286,11 @@ _clk_stm32_register_composite(struct device *dev,
        MGATE_MP1(_id, _name, _parent, _flags, _mgate)
 
 #define KCLK(_id, _name, _parents, _flags, _mgate, _mmux)\
-            COMPOSITE(_id, _name, _parents, CLK_OPS_PARENT_ENABLE | _flags,\
-                 _MGATE_MP1(_mgate),\
-                 _MMUX(_mmux),\
-                 _NO_DIV)
+            COMPOSITE(_id, _name, _parents, CLK_OPS_PARENT_ENABLE |\
+                      CLK_SET_RATE_NO_REPARENT | _flags,\
+                      _MGATE_MP1(_mgate),\
+                      _MMUX(_mmux),\
+                      _NO_DIV)
 
 enum {
        G_SAI1,
@@ -1655,12 +1656,14 @@ static const struct stm32_mux_cfg ker_mux_cfg[M_LAST] = {
 
 static const struct clock_config stm32mp1_clock_cfg[] = {
        /* Oscillator divider */
-       DIV(NO_ID, "clk-hsi-div", "clk-hsi", 0, RCC_HSICFGR, 0, 2,
-           CLK_DIVIDER_READ_ONLY),
+       DIV(NO_ID, "clk-hsi-div", "clk-hsi", CLK_DIVIDER_POWER_OF_TWO,
+           RCC_HSICFGR, 0, 2, CLK_DIVIDER_READ_ONLY),
 
        /*  External / Internal Oscillators */
        GATE_MP1(CK_HSE, "ck_hse", "clk-hse", 0, RCC_OCENSETR, 8, 0),
-       GATE_MP1(CK_CSI, "ck_csi", "clk-csi", 0, RCC_OCENSETR, 4, 0),
+       /* ck_csi is used by IO compensation and should be critical */
+       GATE_MP1(CK_CSI, "ck_csi", "clk-csi", CLK_IS_CRITICAL,
+                RCC_OCENSETR, 4, 0),
        GATE_MP1(CK_HSI, "ck_hsi", "clk-hsi-div", 0, RCC_OCENSETR, 0, 0),
        GATE(CK_LSI, "ck_lsi", "clk-lsi", 0, RCC_RDLSICR, 0, 0),
        GATE(CK_LSE, "ck_lse", "clk-lse", 0, RCC_BDCR, 0, 0),
@@ -1952,14 +1955,14 @@ static const struct clock_config stm32mp1_clock_cfg[] = {
        MGATE_MP1(GPU_K, "gpu_k", "pll2_q", 0, G_GPU),
        MGATE_MP1(DAC12_K, "dac12_k", "ck_lsi", 0, G_DAC12),
 
-       COMPOSITE(ETHPTP_K, "ethptp_k", eth_src, CLK_OPS_PARENT_ENABLE,
+       COMPOSITE(ETHPTP_K, "ethptp_k", eth_src, CLK_OPS_PARENT_ENABLE |
+                 CLK_SET_RATE_NO_REPARENT,
                  _NO_GATE,
                  _MMUX(M_ETHCK),
-                 _DIV(RCC_ETHCKSELR, 4, 4, CLK_DIVIDER_ALLOW_ZERO, NULL)),
+                 _DIV(RCC_ETHCKSELR, 4, 4, 0, NULL)),
 
        /* RTC clock */
-       DIV(NO_ID, "ck_hse_rtc", "ck_hse", 0, RCC_RTCDIVR, 0, 7,
-           CLK_DIVIDER_ALLOW_ZERO),
+       DIV(NO_ID, "ck_hse_rtc", "ck_hse", 0, RCC_RTCDIVR, 0, 6, 0),
 
        COMPOSITE(RTC, "ck_rtc", rtc_src, CLK_OPS_PARENT_ENABLE |
                   CLK_SET_RATE_PARENT,
index ea846f7..0cad574 100644 (file)
@@ -41,6 +41,43 @@ static int twl6040_pdmclk_is_prepared(struct clk_hw *hw)
        return pdmclk->enabled;
 }
 
+static int twl6040_pdmclk_reset_one_clock(struct twl6040_pdmclk *pdmclk,
+                                         unsigned int reg)
+{
+       const u8 reset_mask = TWL6040_HPLLRST;  /* Same for HPPLL and LPPLL */
+       int ret;
+
+       ret = twl6040_set_bits(pdmclk->twl6040, reg, reset_mask);
+       if (ret < 0)
+               return ret;
+
+       ret = twl6040_clear_bits(pdmclk->twl6040, reg, reset_mask);
+       if (ret < 0)
+               return ret;
+
+       return 0;
+}
+
+/*
+ * TWL6040A2 Phoenix Audio IC erratum #6: "PDM Clock Generation Issue At
+ * Cold Temperature". This affects cold boot and deeper idle states it
+ * seems. The workaround consists of resetting HPPLL and LPPLL.
+ */
+static int twl6040_pdmclk_quirk_reset_clocks(struct twl6040_pdmclk *pdmclk)
+{
+       int ret;
+
+       ret = twl6040_pdmclk_reset_one_clock(pdmclk, TWL6040_REG_HPPLLCTL);
+       if (ret)
+               return ret;
+
+       ret = twl6040_pdmclk_reset_one_clock(pdmclk, TWL6040_REG_LPPLLCTL);
+       if (ret)
+               return ret;
+
+       return 0;
+}
+
 static int twl6040_pdmclk_prepare(struct clk_hw *hw)
 {
        struct twl6040_pdmclk *pdmclk = container_of(hw, struct twl6040_pdmclk,
@@ -48,8 +85,20 @@ static int twl6040_pdmclk_prepare(struct clk_hw *hw)
        int ret;
 
        ret = twl6040_power(pdmclk->twl6040, 1);
-       if (!ret)
-               pdmclk->enabled = 1;
+       if (ret)
+               return ret;
+
+       ret = twl6040_pdmclk_quirk_reset_clocks(pdmclk);
+       if (ret)
+               goto out_err;
+
+       pdmclk->enabled = 1;
+
+       return 0;
+
+out_err:
+       dev_err(pdmclk->dev, "%s: error %i\n", __func__, ret);
+       twl6040_power(pdmclk->twl6040, 0);
 
        return ret;
 }
index 5b393e7..7d16ab0 100644 (file)
@@ -262,8 +262,10 @@ static int vc5_mux_set_parent(struct clk_hw *hw, u8 index)
 
                if (vc5->clk_mux_ins == VC5_MUX_IN_XIN)
                        src = VC5_PRIM_SRC_SHDN_EN_XTAL;
-               if (vc5->clk_mux_ins == VC5_MUX_IN_CLKIN)
+               else if (vc5->clk_mux_ins == VC5_MUX_IN_CLKIN)
                        src = VC5_PRIM_SRC_SHDN_EN_CLKIN;
+               else /* Invalid; should have been caught by vc5_probe() */
+                       return -EINVAL;
        }
 
        return regmap_update_bits(vc5->regmap, VC5_PRIM_SRC_SHDN, mask, src);
index 75d13c0..af3882f 100644 (file)
@@ -394,16 +394,19 @@ bool clk_hw_is_prepared(const struct clk_hw *hw)
 {
        return clk_core_is_prepared(hw->core);
 }
+EXPORT_SYMBOL_GPL(clk_hw_is_prepared);
 
 bool clk_hw_rate_is_protected(const struct clk_hw *hw)
 {
        return clk_core_rate_is_protected(hw->core);
 }
+EXPORT_SYMBOL_GPL(clk_hw_rate_is_protected);
 
 bool clk_hw_is_enabled(const struct clk_hw *hw)
 {
        return clk_core_is_enabled(hw->core);
 }
+EXPORT_SYMBOL_GPL(clk_hw_is_enabled);
 
 bool __clk_is_enabled(struct clk *clk)
 {
@@ -1513,9 +1516,19 @@ static int clk_fetch_parent_index(struct clk_core *core,
        if (!parent)
                return -EINVAL;
 
-       for (i = 0; i < core->num_parents; i++)
-               if (clk_core_get_parent_by_index(core, i) == parent)
+       for (i = 0; i < core->num_parents; i++) {
+               if (core->parents[i] == parent)
+                       return i;
+
+               if (core->parents[i])
+                       continue;
+
+               /* Fallback to comparing globally unique names */
+               if (!strcmp(parent->name, core->parent_names[i])) {
+                       core->parents[i] = parent;
                        return i;
+               }
+       }
 
        return -EINVAL;
 }
@@ -2779,7 +2792,7 @@ static void clk_dump_one(struct seq_file *s, struct clk_core *c, int level)
        seq_printf(s, "\"protect_count\": %d,", c->protect_count);
        seq_printf(s, "\"rate\": %lu,", clk_core_get_rate(c));
        seq_printf(s, "\"accuracy\": %lu,", clk_core_get_accuracy(c));
-       seq_printf(s, "\"phase\": %d", clk_core_get_phase(c));
+       seq_printf(s, "\"phase\": %d,", clk_core_get_phase(c));
        seq_printf(s, "\"duty_cycle\": %u",
                   clk_core_get_scaled_duty_cycle(c, 100000));
 }
index 9ab3db8..4cfe396 100644 (file)
@@ -52,6 +52,12 @@ struct clk *of_clk_get(struct device_node *np, int index)
 }
 EXPORT_SYMBOL(of_clk_get);
 
+/*
+ * Beware the return values when np is valid, but no clock provider is found.
+ * If name == NULL, the function returns -ENOENT.
+ * If name != NULL, the function returns -EINVAL. This is because __of_clk_get()
+ * is called even if of_property_match_string() returns an error.
+ */
 static struct clk *__of_clk_get_by_name(struct device_node *np,
                                        const char *dev_id,
                                        const char *name)
@@ -401,6 +407,23 @@ static struct clk_lookup *__clk_register_clkdev(struct clk_hw *hw,
        return cl;
 }
 
+static int do_clk_register_clkdev(struct clk_hw *hw,
+       struct clk_lookup **cl, const char *con_id, const char *dev_id)
+{
+       if (IS_ERR(hw))
+               return PTR_ERR(hw);
+       /*
+        * Since dev_id can be NULL, and NULL is handled specially, we must
+        * pass it as either a NULL format string, or with "%s".
+        */
+       if (dev_id)
+               *cl = __clk_register_clkdev(hw, con_id, "%s", dev_id);
+       else
+               *cl = __clk_register_clkdev(hw, con_id, NULL);
+
+       return *cl ? 0 : -ENOMEM;
+}
+
 /**
  * clk_register_clkdev - register one clock lookup for a struct clk
  * @clk: struct clk to associate with all clk_lookups
@@ -423,17 +446,8 @@ int clk_register_clkdev(struct clk *clk, const char *con_id,
        if (IS_ERR(clk))
                return PTR_ERR(clk);
 
-       /*
-        * Since dev_id can be NULL, and NULL is handled specially, we must
-        * pass it as either a NULL format string, or with "%s".
-        */
-       if (dev_id)
-               cl = __clk_register_clkdev(__clk_get_hw(clk), con_id, "%s",
-                                          dev_id);
-       else
-               cl = __clk_register_clkdev(__clk_get_hw(clk), con_id, NULL);
-
-       return cl ? 0 : -ENOMEM;
+       return do_clk_register_clkdev(__clk_get_hw(clk), &cl, con_id,
+                                             dev_id);
 }
 EXPORT_SYMBOL(clk_register_clkdev);
 
@@ -456,18 +470,75 @@ int clk_hw_register_clkdev(struct clk_hw *hw, const char *con_id,
 {
        struct clk_lookup *cl;
 
-       if (IS_ERR(hw))
-               return PTR_ERR(hw);
+       return do_clk_register_clkdev(hw, &cl, con_id, dev_id);
+}
+EXPORT_SYMBOL(clk_hw_register_clkdev);
 
-       /*
-        * Since dev_id can be NULL, and NULL is handled specially, we must
-        * pass it as either a NULL format string, or with "%s".
-        */
-       if (dev_id)
-               cl = __clk_register_clkdev(hw, con_id, "%s", dev_id);
-       else
-               cl = __clk_register_clkdev(hw, con_id, NULL);
+static void devm_clkdev_release(struct device *dev, void *res)
+{
+       clkdev_drop(*(struct clk_lookup **)res);
+}
+
+static int devm_clk_match_clkdev(struct device *dev, void *res, void *data)
+{
+       struct clk_lookup **l = res;
 
-       return cl ? 0 : -ENOMEM;
+       return *l == data;
 }
-EXPORT_SYMBOL(clk_hw_register_clkdev);
+
+/**
+ * devm_clk_release_clkdev - Resource managed clkdev lookup release
+ * @dev: device this lookup is bound
+ * @con_id: connection ID string on device
+ * @dev_id: format string describing device name
+ *
+ * Drop the clkdev lookup created with devm_clk_hw_register_clkdev.
+ * Normally this function will not need to be called and the resource
+ * management code will ensure that the resource is freed.
+ */
+void devm_clk_release_clkdev(struct device *dev, const char *con_id,
+                            const char *dev_id)
+{
+       struct clk_lookup *cl;
+       int rval;
+
+       cl = clk_find(dev_id, con_id);
+       WARN_ON(!cl);
+       rval = devres_release(dev, devm_clkdev_release,
+                             devm_clk_match_clkdev, cl);
+       WARN_ON(rval);
+}
+EXPORT_SYMBOL(devm_clk_release_clkdev);
+
+/**
+ * devm_clk_hw_register_clkdev - managed clk lookup registration for clk_hw
+ * @dev: device this lookup is bound
+ * @hw: struct clk_hw to associate with all clk_lookups
+ * @con_id: connection ID string on device
+ * @dev_id: format string describing device name
+ *
+ * con_id or dev_id may be NULL as a wildcard, just as in the rest of
+ * clkdev.
+ *
+ * To make things easier for mass registration, we detect error clk_hws
+ * from a previous clk_hw_register_*() call, and return the error code for
+ * those.  This is to permit this function to be called immediately
+ * after clk_hw_register_*().
+ */
+int devm_clk_hw_register_clkdev(struct device *dev, struct clk_hw *hw,
+                               const char *con_id, const char *dev_id)
+{
+       int rval = -ENOMEM;
+       struct clk_lookup **cl;
+
+       cl = devres_alloc(devm_clkdev_release, sizeof(*cl), GFP_KERNEL);
+       if (cl) {
+               rval = do_clk_register_clkdev(hw, cl, con_id, dev_id);
+               if (!rval)
+                       devres_add(dev, cl);
+               else
+                       devres_free(cl);
+       }
+       return rval;
+}
+EXPORT_SYMBOL(devm_clk_hw_register_clkdev);
index 4aae31a..0eaf418 100644 (file)
@@ -8,6 +8,12 @@ config MXC_CLK_SCU
        bool
        depends on IMX_SCU
 
+config CLK_IMX8MM
+       bool "IMX8MM CCM Clock Driver"
+       depends on ARCH_MXC && ARM64
+       help
+           Build the driver for i.MX8MM CCM Clock Driver
+
 config CLK_IMX8MQ
        bool "IMX8MQ CCM Clock Driver"
        depends on ARCH_MXC && ARM64
index 73119fb..0d5180f 100644 (file)
@@ -18,12 +18,14 @@ obj-$(CONFIG_MXC_CLK) += \
        clk-pllv2.o \
        clk-pllv3.o \
        clk-pllv4.o \
-       clk-sccg-pll.o
+       clk-sccg-pll.o \
+       clk-pll14xx.o
 
 obj-$(CONFIG_MXC_CLK_SCU) += \
        clk-scu.o \
        clk-lpcg-scu.o
 
+obj-$(CONFIG_CLK_IMX8MM) += clk-imx8mm.o
 obj-$(CONFIG_CLK_IMX8MQ) += clk-imx8mq.o
 obj-$(CONFIG_CLK_IMX8QXP) += clk-imx8qxp.o clk-imx8qxp-lpcg.o
 
index 527ade1..574fac1 100644 (file)
@@ -123,7 +123,7 @@ static const struct clk_ops imx8m_clk_composite_divider_ops = {
 };
 
 struct clk *imx8m_clk_composite_flags(const char *name,
-                                       const char **parent_names,
+                                       const char * const *parent_names,
                                        int num_parents, void __iomem *reg,
                                        unsigned long flags)
 {
index 0026c39..76b9eb1 100644 (file)
@@ -155,13 +155,14 @@ static int clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct clk_frac_pll *pll = to_clk_frac_pll(hw);
        u32 val, divfi, divff;
-       u64 temp64 = parent_rate;
+       u64 temp64;
        int ret;
 
        parent_rate *= 8;
        rate *= 2;
        divfi = rate / parent_rate;
-       temp64 *= rate - divfi;
+       temp64 = parent_rate * divfi;
+       temp64 = rate - temp64;
        temp64 *= PLL_FRAC_DENOM;
        do_div(temp64, parent_rate);
        divff = temp64;
index fc8e782..e91c826 100644 (file)
@@ -428,6 +428,7 @@ static void __init mx51_clocks_init(struct device_node *np)
        clk[IMX5_CLK_ESDHC4_PER_GATE]   = imx_clk_gate2("esdhc4_per_gate", "esdhc_d_sel", MXC_CCM_CCGR3, 14);
        clk[IMX5_CLK_USB_PHY_GATE]      = imx_clk_gate2("usb_phy_gate", "usb_phy_sel", MXC_CCM_CCGR2, 0);
        clk[IMX5_CLK_HSI2C_GATE]        = imx_clk_gate2("hsi2c_gate", "ipg", MXC_CCM_CCGR1, 22);
+       clk[IMX5_CLK_SCC2_IPG_GATE]     = imx_clk_gate2("scc2_gate", "ipg", MXC_CCM_CCGR1, 30);
        clk[IMX5_CLK_MIPI_HSC1_GATE]    = imx_clk_gate2_flags("mipi_hsc1_gate", "ipg", MXC_CCM_CCGR4, 6, CLK_IS_CRITICAL);
        clk[IMX5_CLK_MIPI_HSC2_GATE]    = imx_clk_gate2_flags("mipi_hsc2_gate", "ipg", MXC_CCM_CCGR4, 8, CLK_IS_CRITICAL);
        clk[IMX5_CLK_MIPI_ESC_GATE]     = imx_clk_gate2_flags("mipi_esc_gate", "ipg", MXC_CCM_CCGR4, 10, CLK_IS_CRITICAL);
index 716eac3..708e7c5 100644 (file)
@@ -471,6 +471,7 @@ static void __init imx6q_clocks_init(struct device_node *ccm_node)
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6q-anatop");
        anatop_base = base = of_iomap(np, 0);
        WARN_ON(!base);
+       of_node_put(np);
 
        /* Audio/video PLL post dividers do not work on i.MX6q revision 1.0 */
        if (clk_on_imx6q() && imx_get_soc_revision() == IMX_CHIP_REVISION_1_0) {
index 18527a3..91558b0 100644 (file)
@@ -151,6 +151,7 @@ static void __init imx6sx_clocks_init(struct device_node *ccm_node)
        np = of_find_compatible_node(NULL, NULL, "fsl,imx6sx-anatop");
        base = of_iomap(np, 0);
        WARN_ON(!base);
+       of_node_put(np);
 
        clks[IMX6SX_PLL1_BYPASS_SRC] = imx_clk_mux("pll1_bypass_src", base + 0x00, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
        clks[IMX6SX_PLL2_BYPASS_SRC] = imx_clk_mux("pll2_bypass_src", base + 0x30, 14, 1, pll_bypass_src_sels, ARRAY_SIZE(pll_bypass_src_sels));
index 06c105d..cfbd8d4 100644 (file)
@@ -404,6 +404,7 @@ static void __init imx7d_clocks_init(struct device_node *ccm_node)
        np = of_find_compatible_node(NULL, NULL, "fsl,imx7d-anatop");
        base = of_iomap(np, 0);
        WARN_ON(!base);
+       of_node_put(np);
 
        clks[IMX7D_PLL_ARM_MAIN_SRC]  = imx_clk_mux("pll_arm_main_src", base + 0x60, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
        clks[IMX7D_PLL_DRAM_MAIN_SRC] = imx_clk_mux("pll_dram_main_src", base + 0x70, 14, 2, pll_bypass_src_sel, ARRAY_SIZE(pll_bypass_src_sel));
index 4e18f62..ce30663 100644 (file)
@@ -48,8 +48,8 @@ static void __init imx7ulp_clk_scg1_init(struct device_node *np)
        struct clk_hw **clks;
        void __iomem *base;
 
-       clk_data = kzalloc(sizeof(*clk_data) + sizeof(*clk_data->hws) *
-                          IMX7ULP_CLK_SCG1_END, GFP_KERNEL);
+       clk_data = kzalloc(struct_size(clk_data, hws, IMX7ULP_CLK_SCG1_END),
+                          GFP_KERNEL);
        if (!clk_data)
                return;
 
@@ -136,8 +136,8 @@ static void __init imx7ulp_clk_pcc2_init(struct device_node *np)
        struct clk_hw **clks;
        void __iomem *base;
 
-       clk_data = kzalloc(sizeof(*clk_data) + sizeof(*clk_data->hws) *
-                          IMX7ULP_CLK_PCC2_END, GFP_KERNEL);
+       clk_data = kzalloc(struct_size(clk_data, hws, IMX7ULP_CLK_PCC2_END),
+                          GFP_KERNEL);
        if (!clk_data)
                return;
 
@@ -183,8 +183,8 @@ static void __init imx7ulp_clk_pcc3_init(struct device_node *np)
        struct clk_hw **clks;
        void __iomem *base;
 
-       clk_data = kzalloc(sizeof(*clk_data) + sizeof(*clk_data->hws) *
-                          IMX7ULP_CLK_PCC3_END, GFP_KERNEL);
+       clk_data = kzalloc(struct_size(clk_data, hws, IMX7ULP_CLK_PCC3_END),
+                          GFP_KERNEL);
        if (!clk_data)
                return;
 
@@ -228,8 +228,8 @@ static void __init imx7ulp_clk_smc1_init(struct device_node *np)
        struct clk_hw **clks;
        void __iomem *base;
 
-       clk_data = kzalloc(sizeof(*clk_data) + sizeof(*clk_data->hws) *
-                          IMX7ULP_CLK_SMC1_END, GFP_KERNEL);
+       clk_data = kzalloc(struct_size(clk_data, hws, IMX7ULP_CLK_SMC1_END),
+                          GFP_KERNEL);
        if (!clk_data)
                return;
 
diff --git a/drivers/clk/imx/clk-imx8mm.c b/drivers/clk/imx/clk-imx8mm.c
new file mode 100644 (file)
index 0000000..1ef8438
--- /dev/null
@@ -0,0 +1,675 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2017-2018 NXP.
+ */
+
+#include <dt-bindings/clock/imx8mm-clock.h>
+#include <linux/clk.h>
+#include <linux/err.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/types.h>
+
+#include "clk.h"
+
+static u32 share_count_sai1;
+static u32 share_count_sai2;
+static u32 share_count_sai3;
+static u32 share_count_sai4;
+static u32 share_count_sai5;
+static u32 share_count_sai6;
+static u32 share_count_dcss;
+static u32 share_count_pdm;
+static u32 share_count_nand;
+
+#define PLL_1416X_RATE(_rate, _m, _p, _s)              \
+       {                                               \
+               .rate   =       (_rate),                \
+               .mdiv   =       (_m),                   \
+               .pdiv   =       (_p),                   \
+               .sdiv   =       (_s),                   \
+       }
+
+#define PLL_1443X_RATE(_rate, _m, _p, _s, _k)          \
+       {                                               \
+               .rate   =       (_rate),                \
+               .mdiv   =       (_m),                   \
+               .pdiv   =       (_p),                   \
+               .sdiv   =       (_s),                   \
+               .kdiv   =       (_k),                   \
+       }
+
+static const struct imx_pll14xx_rate_table imx8mm_pll1416x_tbl[] = {
+       PLL_1416X_RATE(1800000000U, 225, 3, 0),
+       PLL_1416X_RATE(1600000000U, 200, 3, 0),
+       PLL_1416X_RATE(1200000000U, 300, 3, 1),
+       PLL_1416X_RATE(1000000000U, 250, 3, 1),
+       PLL_1416X_RATE(800000000U,  200, 3, 1),
+       PLL_1416X_RATE(750000000U,  250, 2, 2),
+       PLL_1416X_RATE(700000000U,  350, 3, 2),
+       PLL_1416X_RATE(600000000U,  300, 3, 2),
+};
+
+static const struct imx_pll14xx_rate_table imx8mm_audiopll_tbl[] = {
+       PLL_1443X_RATE(786432000U, 655, 5, 2, 23593),
+       PLL_1443X_RATE(722534400U, 301, 5, 1, 3670),
+};
+
+static const struct imx_pll14xx_rate_table imx8mm_videopll_tbl[] = {
+       PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
+       PLL_1443X_RATE(594000000U, 198, 2, 2, 0),
+};
+
+static const struct imx_pll14xx_rate_table imx8mm_drampll_tbl[] = {
+       PLL_1443X_RATE(650000000U, 325, 3, 2, 0),
+};
+
+static struct imx_pll14xx_clk imx8mm_audio_pll __initdata = {
+               .type = PLL_1443X,
+               .rate_table = imx8mm_audiopll_tbl,
+               .rate_count = ARRAY_SIZE(imx8mm_audiopll_tbl),
+};
+
+static struct imx_pll14xx_clk imx8mm_video_pll __initdata = {
+               .type = PLL_1443X,
+               .rate_table = imx8mm_videopll_tbl,
+               .rate_count = ARRAY_SIZE(imx8mm_videopll_tbl),
+};
+
+static struct imx_pll14xx_clk imx8mm_dram_pll __initdata = {
+               .type = PLL_1443X,
+               .rate_table = imx8mm_drampll_tbl,
+               .rate_count = ARRAY_SIZE(imx8mm_drampll_tbl),
+};
+
+static struct imx_pll14xx_clk imx8mm_arm_pll __initdata = {
+               .type = PLL_1416X,
+               .rate_table = imx8mm_pll1416x_tbl,
+               .rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
+};
+
+static struct imx_pll14xx_clk imx8mm_gpu_pll __initdata = {
+               .type = PLL_1416X,
+               .rate_table = imx8mm_pll1416x_tbl,
+               .rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
+};
+
+static struct imx_pll14xx_clk imx8mm_vpu_pll __initdata = {
+               .type = PLL_1416X,
+               .rate_table = imx8mm_pll1416x_tbl,
+               .rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
+};
+
+static struct imx_pll14xx_clk imx8mm_sys_pll __initdata = {
+               .type = PLL_1416X,
+               .rate_table = imx8mm_pll1416x_tbl,
+               .rate_count = ARRAY_SIZE(imx8mm_pll1416x_tbl),
+};
+
+static const char *pll_ref_sels[] = { "osc_24m", "dummy", "dummy", "dummy", };
+static const char *audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
+static const char *audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
+static const char *video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", };
+static const char *dram_pll_bypass_sels[] = {"dram_pll", "dram_pll_ref_sel", };
+static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char *sys_pll1_bypass_sels[] = {"sys_pll1", "sys_pll1_ref_sel", };
+static const char *sys_pll2_bypass_sels[] = {"sys_pll2", "sys_pll2_ref_sel", };
+static const char *sys_pll3_bypass_sels[] = {"sys_pll3", "sys_pll3_ref_sel", };
+
+/* CCM ROOT */
+static const char *imx8mm_a53_sels[] = {"osc_24m", "arm_pll_out", "sys_pll2_500m", "sys_pll2_1000m",
+                                       "sys_pll1_800m", "sys_pll1_400m", "audio_pll1_out", "sys_pll3_out", };
+
+static const char *imx8mm_m4_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_250m", "sys_pll1_266m",
+                                      "sys_pll1_800m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", };
+
+static const char *imx8mm_vpu_sels[] = {"osc_24m", "arm_pll_out", "sys_pll2_500m", "sys_pll2_1000m",
+                                       "sys_pll1_800m", "sys_pll1_400m", "audio_pll1_out", "vpu_pll_out", };
+
+static const char *imx8mm_gpu3d_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m", "sys_pll3_out",
+                                         "sys_pll2_1000m", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mm_gpu2d_sels[] = {"osc_24m", "gpu_pll_out", "sys_pll1_800m", "sys_pll3_out",
+                                         "sys_pll2_1000m", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mm_main_axi_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll1_800m", "sys_pll2_250m",
+                                            "sys_pll2_1000m", "audio_pll1_out", "video_pll1_out", "sys_pll1_100m",};
+
+static const char *imx8mm_enet_axi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m", "sys_pll2_250m",
+                                            "sys_pll2_200m", "audio_pll1_out", "video_pll1_out", "sys_pll3_out", };
+
+static const char *imx8mm_nand_usdhc_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll1_800m", "sys_pll2_200m",
+                                              "sys_pll1_133m", "sys_pll3_out", "sys_pll2_250m", "audio_pll1_out", };
+
+static const char *imx8mm_vpu_bus_sels[] = {"osc_24m", "sys_pll1_800m", "vpu_pll_out", "audio_pll2_out",
+                                           "sys_pll3_out", "sys_pll2_1000m", "sys_pll2_200m", "sys_pll1_100m", };
+
+static const char *imx8mm_disp_axi_sels[] = {"osc_24m", "sys_pll2_1000m", "sys_pll1_800m", "sys_pll3_out",
+                                            "sys_pll1_40m", "audio_pll2_out", "clk_ext1", "clk_ext4", };
+
+static const char *imx8mm_disp_apb_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll1_800m", "sys_pll3_out",
+                                            "sys_pll1_40m", "audio_pll2_out", "clk_ext1", "clk_ext3", };
+
+static const char *imx8mm_disp_rtrm_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll2_200m", "sys_pll2_1000m",
+                                             "audio_pll1_out", "video_pll1_out", "clk_ext2", "clk_ext3", };
+
+static const char *imx8mm_usb_bus_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m", "sys_pll2_100m",
+                                           "sys_pll2_200m", "clk_ext2", "clk_ext4", "audio_pll2_out", };
+
+static const char *imx8mm_gpu_axi_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out", "sys_pll3_out", "sys_pll2_1000m",
+                                           "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mm_gpu_ahb_sels[] = {"osc_24m", "sys_pll1_800m", "gpu_pll_out", "sys_pll3_out", "sys_pll2_1000m",
+                                           "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mm_noc_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll3_out", "sys_pll2_1000m", "sys_pll2_500m",
+                                       "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mm_noc_apb_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll3_out", "sys_pll2_333m", "sys_pll2_200m",
+                                           "sys_pll1_800m", "audio_pll1_out", "video_pll1_out", };
+
+static const char *imx8mm_ahb_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_800m", "sys_pll1_400m",
+                                       "sys_pll2_125m", "sys_pll3_out", "audio_pll1_out", "video_pll1_out", };
+
+static const char *imx8mm_audio_ahb_sels[] = {"osc_24m", "sys_pll2_500m", "sys_pll1_800m", "sys_pll2_1000m",
+                                             "sys_pll2_166m", "sys_pll3_out", "audio_pll1_out", "video_pll1_out", };
+
+static const char *imx8mm_dram_alt_sels[] = {"osc_24m", "sys_pll1_800m", "sys_pll1_100m", "sys_pll2_500m",
+                                            "sys_pll2_1000m", "sys_pll3_out", "audio_pll1_out", "sys_pll1_266m", };
+
+static const char *imx8mm_dram_apb_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m", "sys_pll1_160m",
+                                            "sys_pll1_800m", "sys_pll3_out", "sys_pll2_250m", "audio_pll2_out", };
+
+static const char *imx8mm_vpu_g1_sels[] = {"osc_24m", "vpu_pll_out", "sys_pll1_800m", "sys_pll2_1000m",
+                                          "sys_pll1_100m", "sys_pll2_125m", "sys_pll3_out", "audio_pll1_out", };
+
+static const char *imx8mm_vpu_g2_sels[] = {"osc_24m", "vpu_pll_out", "sys_pll1_800m", "sys_pll2_1000m",
+                                          "sys_pll1_100m", "sys_pll2_125m", "sys_pll3_out", "audio_pll1_out", };
+
+static const char *imx8mm_disp_dtrc_sels[] = {"osc_24m", "video_pll2_out", "sys_pll1_800m", "sys_pll2_1000m",
+                                             "sys_pll1_160m", "video_pll1_out", "sys_pll3_out", "audio_pll2_out", };
+
+static const char *imx8mm_disp_dc8000_sels[] = {"osc_24m", "video_pll2_out", "sys_pll1_800m", "sys_pll2_1000m",
+                                               "sys_pll1_160m", "video_pll1_out", "sys_pll3_out", "audio_pll2_out", };
+
+static const char *imx8mm_pcie1_ctrl_sels[] = {"osc_24m", "sys_pll2_250m", "sys_pll2_200m", "sys_pll1_266m",
+                                              "sys_pll1_800m", "sys_pll2_500m", "sys_pll2_333m", "sys_pll3_out", };
+
+static const char *imx8mm_pcie1_phy_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll2_500m", "clk_ext1", "clk_ext2",
+                                             "clk_ext3", "clk_ext4", "sys_pll1_400m", };
+
+static const char *imx8mm_pcie1_aux_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_50m", "sys_pll3_out",
+                                             "sys_pll2_100m", "sys_pll1_80m", "sys_pll1_160m", "sys_pll1_200m", };
+
+static const char *imx8mm_dc_pixel_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out",
+                                            "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", "clk_ext4", };
+
+static const char *imx8mm_lcdif_pixel_sels[] = {"osc_24m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out",
+                                               "sys_pll1_800m", "sys_pll2_1000m", "sys_pll3_out", "clk_ext4", };
+
+static const char *imx8mm_sai1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+                                        "sys_pll1_133m", "osc_hdmi", "clk_ext1", "clk_ext2", };
+
+static const char *imx8mm_sai2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+                                        "sys_pll1_133m", "osc_hdmi", "clk_ext2", "clk_ext3", };
+
+static const char *imx8mm_sai3_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+                                        "sys_pll1_133m", "osc_hdmi", "clk_ext3", "clk_ext4", };
+
+static const char *imx8mm_sai4_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+                                        "sys_pll1_133m", "osc_hdmi", "clk_ext1", "clk_ext2", };
+
+static const char *imx8mm_sai5_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+                                        "sys_pll1_133m", "osc_hdmi", "clk_ext2", "clk_ext3", };
+
+static const char *imx8mm_sai6_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+                                        "sys_pll1_133m", "osc_hdmi", "clk_ext3", "clk_ext4", };
+
+static const char *imx8mm_spdif1_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+                                          "sys_pll1_133m", "osc_hdmi", "clk_ext2", "clk_ext3", };
+
+static const char *imx8mm_spdif2_sels[] = {"osc_24m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out",
+                                          "sys_pll1_133m", "osc_hdmi", "clk_ext3", "clk_ext4", };
+
+static const char *imx8mm_enet_ref_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_50m", "sys_pll2_100m",
+                                            "sys_pll1_160m", "audio_pll1_out", "video_pll1_out", "clk_ext4", };
+
+static const char *imx8mm_enet_timer_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out", "clk_ext1", "clk_ext2",
+                                              "clk_ext3", "clk_ext4", "video_pll1_out", };
+
+static const char *imx8mm_enet_phy_sels[] = {"osc_24m", "sys_pll2_50m", "sys_pll2_125m", "sys_pll2_200m",
+                                            "sys_pll2_500m", "video_pll1_out", "audio_pll2_out", };
+
+static const char *imx8mm_nand_sels[] = {"osc_24m", "sys_pll2_500m", "audio_pll1_out", "sys_pll1_400m",
+                                        "audio_pll2_out", "sys_pll3_out", "sys_pll2_250m", "video_pll1_out", };
+
+static const char *imx8mm_qspi_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
+                                        "audio_pll2_out", "sys_pll1_266m", "sys_pll3_out", "sys_pll1_100m", };
+
+static const char *imx8mm_usdhc1_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
+                                          "sys_pll3_out", "sys_pll1_266m", "audio_pll2_out", "sys_pll1_100m", };
+
+static const char *imx8mm_usdhc2_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
+                                          "sys_pll3_out", "sys_pll1_266m", "audio_pll2_out", "sys_pll1_100m", };
+
+static const char *imx8mm_i2c1_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+                                        "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_i2c2_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+                                        "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_i2c3_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+                                        "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_i2c4_sels[] = {"osc_24m", "sys_pll1_160m", "sys_pll2_50m", "sys_pll3_out", "audio_pll1_out",
+                                        "video_pll1_out", "audio_pll2_out", "sys_pll1_133m", };
+
+static const char *imx8mm_uart1_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m", "sys_pll2_100m",
+                                         "sys_pll3_out", "clk_ext2", "clk_ext4", "audio_pll2_out", };
+
+static const char *imx8mm_uart2_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m", "sys_pll2_100m",
+                                         "sys_pll3_out", "clk_ext2", "clk_ext3", "audio_pll2_out", };
+
+static const char *imx8mm_uart3_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m", "sys_pll2_100m",
+                                         "sys_pll3_out", "clk_ext2", "clk_ext4", "audio_pll2_out", };
+
+static const char *imx8mm_uart4_sels[] = {"osc_24m", "sys_pll1_80m", "sys_pll2_200m", "sys_pll2_100m",
+                                         "sys_pll3_out", "clk_ext2", "clk_ext3", "audio_pll2_out", };
+
+static const char *imx8mm_usb_core_sels[] = {"osc_24m", "sys_pll1_100m", "sys_pll1_40m", "sys_pll2_100m",
+                                            "sys_pll2_200m", "clk_ext2", "clk_ext3", "audio_pll2_out", };
+
+static const char *imx8mm_usb_phy_sels[] = {"osc_24m", "sys_pll1_100m", "sys_pll1_40m", "sys_pll2_100m",
+                                            "sys_pll2_200m", "clk_ext2", "clk_ext3", "audio_pll2_out", };
+
+static const char *imx8mm_ecspi1_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m", "sys_pll1_160m",
+                                          "sys_pll1_800m", "sys_pll3_out", "sys_pll2_250m", "audio_pll2_out", };
+
+static const char *imx8mm_ecspi2_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m", "sys_pll1_160m",
+                                          "sys_pll1_800m", "sys_pll3_out", "sys_pll2_250m", "audio_pll2_out", };
+
+static const char *imx8mm_pwm1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m",
+                                        "sys_pll3_out", "clk_ext1", "sys_pll1_80m", "video_pll1_out", };
+
+static const char *imx8mm_pwm2_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m",
+                                        "sys_pll3_out", "clk_ext1", "sys_pll1_80m", "video_pll1_out", };
+
+static const char *imx8mm_pwm3_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m",
+                                        "sys3_pll2_out", "clk_ext2", "sys_pll1_80m", "video_pll1_out", };
+
+static const char *imx8mm_pwm4_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_160m", "sys_pll1_40m",
+                                        "sys_pll3_out", "clk_ext2", "sys_pll1_80m", "video_pll1_out", };
+
+static const char *imx8mm_gpt1_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_400m", "sys_pll1_40m",
+                                        "video_pll1_out", "sys_pll1_800m", "audio_pll1_out", "clk_ext1" };
+
+static const char *imx8mm_wdog_sels[] = {"osc_24m", "sys_pll1_133m", "sys_pll1_160m", "vpu_pll_out",
+                                        "sys_pll2_125m", "sys_pll3_out", "sys_pll1_80m", "sys_pll2_166m", };
+
+static const char *imx8mm_wrclk_sels[] = {"osc_24m", "sys_pll1_40m", "vpu_pll_out", "sys_pll3_out", "sys_pll2_200m",
+                                         "sys_pll1_266m", "sys_pll2_500m", "sys_pll1_100m", };
+
+static const char *imx8mm_dsi_core_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m", "sys_pll1_800m",
+                                            "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll1_out", };
+
+static const char *imx8mm_dsi_phy_sels[] = {"osc_24m", "sys_pll2_125m", "sys_pll2_100m", "sys_pll1_800m",
+                                           "sys_pll2_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
+
+static const char *imx8mm_dsi_dbi_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_100m", "sys_pll1_800m",
+                                           "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll1_out", };
+
+static const char *imx8mm_usdhc3_sels[] = {"osc_24m", "sys_pll1_400m", "sys_pll1_800m", "sys_pll2_500m",
+                                          "sys_pll3_out", "sys_pll1_266m", "audio_pll2_clk", "sys_pll1_100m", };
+
+static const char *imx8mm_csi1_core_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m", "sys_pll1_800m",
+                                             "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll1_out", };
+
+static const char *imx8mm_csi1_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m", "sys_pll1_800m",
+                                            "sys_pll2_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
+
+static const char *imx8mm_csi1_esc_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m", "sys_pll1_800m",
+                                            "sys_pll2_1000m", "sys_pll3_out", "clk_ext3", "audio_pll2_out", };
+
+static const char *imx8mm_csi2_core_sels[] = {"osc_24m", "sys_pll1_266m", "sys_pll2_250m", "sys_pll1_800m",
+                                             "sys_pll2_1000m", "sys_pll3_out", "audio_pll2_out", "video_pll1_out", };
+
+static const char *imx8mm_csi2_phy_sels[] = {"osc_24m", "sys_pll2_333m", "sys_pll2_100m", "sys_pll1_800m",
+                                            "sys_pll2_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
+
+static const char *imx8mm_csi2_esc_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll1_80m", "sys_pll1_800m",
+                                            "sys_pll2_1000m", "sys_pll3_out", "clk_ext3", "audio_pll2_out", };
+
+static const char *imx8mm_pcie2_ctrl_sels[] = {"osc_24m", "sys_pll2_250m", "sys_pll2_200m", "sys_pll1_266m",
+                                              "sys_pll1_800m", "sys_pll2_500m", "sys_pll2_333m", "sys_pll3_out", };
+
+static const char *imx8mm_pcie2_phy_sels[] = {"osc_24m", "sys_pll2_100m", "sys_pll2_500m", "clk_ext1",
+                                             "clk_ext2", "clk_ext3", "clk_ext4", "sys_pll1_400m", };
+
+static const char *imx8mm_pcie2_aux_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll2_50m", "sys_pll3_out",
+                                             "sys_pll2_100m", "sys_pll1_80m", "sys_pll1_160m", "sys_pll1_200m", };
+
+static const char *imx8mm_ecspi3_sels[] = {"osc_24m", "sys_pll2_200m", "sys_pll1_40m", "sys_pll1_160m",
+                                          "sys_pll1_800m", "sys_pll3_out", "sys_pll2_250m", "audio_pll2_out", };
+
+static const char *imx8mm_pdm_sels[] = {"osc_24m", "sys_pll2_100m", "audio_pll1_out", "sys_pll1_800m",
+                                       "sys_pll2_1000m", "sys_pll3_out", "clk_ext3", "audio_pll2_out", };
+
+static const char *imx8mm_vpu_h1_sels[] = {"osc_24m", "vpu_pll_out", "sys_pll1_800m", "sys_pll2_1000m",
+                                          "audio_pll2_clk", "sys_pll2_125m", "sys_pll3_clk", "audio_pll1_out", };
+
+static const char *imx8mm_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
+
+static const char *imx8mm_clko1_sels[] = {"osc_24m", "sys_pll1_800m", "osc_27m", "sys_pll1_200m", "audio_pll2_clk",
+                                        "vpu_pll", "sys_pll1_80m", };
+
+static struct clk *clks[IMX8MM_CLK_END];
+static struct clk_onecell_data clk_data;
+
+static struct clk ** const uart_clks[] __initconst = {
+       &clks[IMX8MM_CLK_UART1_ROOT],
+       &clks[IMX8MM_CLK_UART2_ROOT],
+       &clks[IMX8MM_CLK_UART3_ROOT],
+       &clks[IMX8MM_CLK_UART4_ROOT],
+       NULL
+};
+
+static int __init imx8mm_clocks_init(struct device_node *ccm_node)
+{
+       struct device_node *np;
+       void __iomem *base;
+       int ret;
+
+       clks[IMX8MM_CLK_DUMMY] = imx_clk_fixed("dummy", 0);
+       clks[IMX8MM_CLK_24M] = of_clk_get_by_name(ccm_node, "osc_24m");
+       clks[IMX8MM_CLK_32K] = of_clk_get_by_name(ccm_node, "osc_32k");
+       clks[IMX8MM_CLK_EXT1] = of_clk_get_by_name(ccm_node, "clk_ext1");
+       clks[IMX8MM_CLK_EXT2] = of_clk_get_by_name(ccm_node, "clk_ext2");
+       clks[IMX8MM_CLK_EXT3] = of_clk_get_by_name(ccm_node, "clk_ext3");
+       clks[IMX8MM_CLK_EXT4] = of_clk_get_by_name(ccm_node, "clk_ext4");
+
+       np = of_find_compatible_node(NULL, NULL, "fsl,imx8mm-anatop");
+       base = of_iomap(np, 0);
+       if (WARN_ON(!base))
+               return -ENOMEM;
+
+       clks[IMX8MM_AUDIO_PLL1_REF_SEL] = imx_clk_mux("audio_pll1_ref_sel", base + 0x0, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+       clks[IMX8MM_AUDIO_PLL2_REF_SEL] = imx_clk_mux("audio_pll2_ref_sel", base + 0x14, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+       clks[IMX8MM_VIDEO_PLL1_REF_SEL] = imx_clk_mux("video_pll1_ref_sel", base + 0x28, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+       clks[IMX8MM_DRAM_PLL_REF_SEL] = imx_clk_mux("dram_pll_ref_sel", base + 0x50, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+       clks[IMX8MM_GPU_PLL_REF_SEL] = imx_clk_mux("gpu_pll_ref_sel", base + 0x64, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+       clks[IMX8MM_VPU_PLL_REF_SEL] = imx_clk_mux("vpu_pll_ref_sel", base + 0x74, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+       clks[IMX8MM_ARM_PLL_REF_SEL] = imx_clk_mux("arm_pll_ref_sel", base + 0x84, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+       clks[IMX8MM_SYS_PLL1_REF_SEL] = imx_clk_mux("sys_pll1_ref_sel", base + 0x94, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+       clks[IMX8MM_SYS_PLL2_REF_SEL] = imx_clk_mux("sys_pll2_ref_sel", base + 0x104, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+       clks[IMX8MM_SYS_PLL3_REF_SEL] = imx_clk_mux("sys_pll3_ref_sel", base + 0x114, 0, 2, pll_ref_sels, ARRAY_SIZE(pll_ref_sels));
+
+       clks[IMX8MM_AUDIO_PLL1] = imx_clk_pll14xx("audio_pll1", "audio_pll1_ref_sel", base, &imx8mm_audio_pll);
+       clks[IMX8MM_AUDIO_PLL2] = imx_clk_pll14xx("audio_pll2", "audio_pll2_ref_sel", base + 0x14, &imx8mm_audio_pll);
+       clks[IMX8MM_VIDEO_PLL1] = imx_clk_pll14xx("video_pll1", "video_pll1_ref_sel", base + 0x28, &imx8mm_video_pll);
+       clks[IMX8MM_DRAM_PLL] = imx_clk_pll14xx("dram_pll", "dram_pll_ref_sel", base + 0x50, &imx8mm_dram_pll);
+       clks[IMX8MM_GPU_PLL] = imx_clk_pll14xx("gpu_pll", "gpu_pll_ref_sel", base + 0x64, &imx8mm_gpu_pll);
+       clks[IMX8MM_VPU_PLL] = imx_clk_pll14xx("vpu_pll", "vpu_pll_ref_sel", base + 0x74, &imx8mm_vpu_pll);
+       clks[IMX8MM_ARM_PLL] = imx_clk_pll14xx("arm_pll", "arm_pll_ref_sel", base + 0x84, &imx8mm_arm_pll);
+       clks[IMX8MM_SYS_PLL1] = imx_clk_pll14xx("sys_pll1", "sys_pll1_ref_sel", base + 0x94, &imx8mm_sys_pll);
+       clks[IMX8MM_SYS_PLL2] = imx_clk_pll14xx("sys_pll2", "sys_pll2_ref_sel", base + 0x104, &imx8mm_sys_pll);
+       clks[IMX8MM_SYS_PLL3] = imx_clk_pll14xx("sys_pll3", "sys_pll3_ref_sel", base + 0x114, &imx8mm_sys_pll);
+
+       /* PLL bypass out */
+       clks[IMX8MM_AUDIO_PLL1_BYPASS] = imx_clk_mux_flags("audio_pll1_bypass", base, 4, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX8MM_AUDIO_PLL2_BYPASS] = imx_clk_mux_flags("audio_pll2_bypass", base + 0x14, 4, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX8MM_VIDEO_PLL1_BYPASS] = imx_clk_mux_flags("video_pll1_bypass", base + 0x28, 4, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX8MM_DRAM_PLL_BYPASS] = imx_clk_mux_flags("dram_pll_bypass", base + 0x50, 4, 1, dram_pll_bypass_sels, ARRAY_SIZE(dram_pll_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX8MM_GPU_PLL_BYPASS] = imx_clk_mux_flags("gpu_pll_bypass", base + 0x64, 4, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX8MM_VPU_PLL_BYPASS] = imx_clk_mux_flags("vpu_pll_bypass", base + 0x74, 4, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX8MM_ARM_PLL_BYPASS] = imx_clk_mux_flags("arm_pll_bypass", base + 0x84, 4, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX8MM_SYS_PLL1_BYPASS] = imx_clk_mux_flags("sys_pll1_bypass", base + 0x94, 4, 1, sys_pll1_bypass_sels, ARRAY_SIZE(sys_pll1_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX8MM_SYS_PLL2_BYPASS] = imx_clk_mux_flags("sys_pll2_bypass", base + 0x104, 4, 1, sys_pll2_bypass_sels, ARRAY_SIZE(sys_pll2_bypass_sels), CLK_SET_RATE_PARENT);
+       clks[IMX8MM_SYS_PLL3_BYPASS] = imx_clk_mux_flags("sys_pll3_bypass", base + 0x114, 4, 1, sys_pll3_bypass_sels, ARRAY_SIZE(sys_pll3_bypass_sels), CLK_SET_RATE_PARENT);
+
+       /* unbypass all the plls */
+       clk_set_parent(clks[IMX8MM_AUDIO_PLL1_BYPASS], clks[IMX8MM_AUDIO_PLL1]);
+       clk_set_parent(clks[IMX8MM_AUDIO_PLL2_BYPASS], clks[IMX8MM_AUDIO_PLL2]);
+       clk_set_parent(clks[IMX8MM_VIDEO_PLL1_BYPASS], clks[IMX8MM_VIDEO_PLL1]);
+       clk_set_parent(clks[IMX8MM_DRAM_PLL_BYPASS], clks[IMX8MM_DRAM_PLL]);
+       clk_set_parent(clks[IMX8MM_GPU_PLL_BYPASS], clks[IMX8MM_GPU_PLL]);
+       clk_set_parent(clks[IMX8MM_VPU_PLL_BYPASS], clks[IMX8MM_VPU_PLL]);
+       clk_set_parent(clks[IMX8MM_ARM_PLL_BYPASS], clks[IMX8MM_ARM_PLL]);
+       clk_set_parent(clks[IMX8MM_SYS_PLL1_BYPASS], clks[IMX8MM_SYS_PLL1]);
+       clk_set_parent(clks[IMX8MM_SYS_PLL2_BYPASS], clks[IMX8MM_SYS_PLL2]);
+       clk_set_parent(clks[IMX8MM_SYS_PLL3_BYPASS], clks[IMX8MM_SYS_PLL3]);
+
+       /* PLL out gate */
+       clks[IMX8MM_AUDIO_PLL1_OUT] = imx_clk_gate("audio_pll1_out", "audio_pll1_bypass", base, 13);
+       clks[IMX8MM_AUDIO_PLL2_OUT] = imx_clk_gate("audio_pll2_out", "audio_pll2_bypass", base + 0x14, 13);
+       clks[IMX8MM_VIDEO_PLL1_OUT] = imx_clk_gate("video_pll1_out", "video_pll1_bypass", base + 0x28, 13);
+       clks[IMX8MM_DRAM_PLL_OUT] = imx_clk_gate("dram_pll_out", "dram_pll_bypass", base + 0x50, 13);
+       clks[IMX8MM_GPU_PLL_OUT] = imx_clk_gate("gpu_pll_out", "gpu_pll_bypass", base + 0x64, 13);
+       clks[IMX8MM_VPU_PLL_OUT] = imx_clk_gate("vpu_pll_out", "vpu_pll_bypass", base + 0x74, 13);
+       clks[IMX8MM_ARM_PLL_OUT] = imx_clk_gate("arm_pll_out", "arm_pll_bypass", base + 0x84, 13);
+       clks[IMX8MM_SYS_PLL1_OUT] = imx_clk_gate("sys_pll1_out", "sys_pll1_bypass", base + 0x94, 13);
+       clks[IMX8MM_SYS_PLL2_OUT] = imx_clk_gate("sys_pll2_out", "sys_pll2_bypass", base + 0x104, 13);
+       clks[IMX8MM_SYS_PLL3_OUT] = imx_clk_gate("sys_pll3_out", "sys_pll3_bypass", base + 0x114, 13);
+
+       /* SYS PLL fixed output */
+       clks[IMX8MM_SYS_PLL1_40M] = imx_clk_fixed_factor("sys_pll1_40m", "sys_pll1_out", 1, 20);
+       clks[IMX8MM_SYS_PLL1_80M] = imx_clk_fixed_factor("sys_pll1_80m", "sys_pll1_out", 1, 10);
+       clks[IMX8MM_SYS_PLL1_100M] = imx_clk_fixed_factor("sys_pll1_100m", "sys_pll1_out", 1, 8);
+       clks[IMX8MM_SYS_PLL1_133M] = imx_clk_fixed_factor("sys_pll1_133m", "sys_pll1_out", 1, 6);
+       clks[IMX8MM_SYS_PLL1_160M] = imx_clk_fixed_factor("sys_pll1_160m", "sys_pll1_out", 1, 5);
+       clks[IMX8MM_SYS_PLL1_200M] = imx_clk_fixed_factor("sys_pll1_200m", "sys_pll1_out", 1, 4);
+       clks[IMX8MM_SYS_PLL1_266M] = imx_clk_fixed_factor("sys_pll1_266m", "sys_pll1_out", 1, 3);
+       clks[IMX8MM_SYS_PLL1_400M] = imx_clk_fixed_factor("sys_pll1_400m", "sys_pll1_out", 1, 2);
+       clks[IMX8MM_SYS_PLL1_800M] = imx_clk_fixed_factor("sys_pll1_800m", "sys_pll1_out", 1, 1);
+
+       clks[IMX8MM_SYS_PLL2_50M] = imx_clk_fixed_factor("sys_pll2_50m", "sys_pll2_out", 1, 20);
+       clks[IMX8MM_SYS_PLL2_100M] = imx_clk_fixed_factor("sys_pll2_100m", "sys_pll2_out", 1, 10);
+       clks[IMX8MM_SYS_PLL2_125M] = imx_clk_fixed_factor("sys_pll2_125m", "sys_pll2_out", 1, 8);
+       clks[IMX8MM_SYS_PLL2_166M] = imx_clk_fixed_factor("sys_pll2_166m", "sys_pll2_out", 1, 6);
+       clks[IMX8MM_SYS_PLL2_200M] = imx_clk_fixed_factor("sys_pll2_200m", "sys_pll2_out", 1, 5);
+       clks[IMX8MM_SYS_PLL2_250M] = imx_clk_fixed_factor("sys_pll2_250m", "sys_pll2_out", 1, 4);
+       clks[IMX8MM_SYS_PLL2_333M] = imx_clk_fixed_factor("sys_pll2_333m", "sys_pll2_out", 1, 3);
+       clks[IMX8MM_SYS_PLL2_500M] = imx_clk_fixed_factor("sys_pll2_500m", "sys_pll2_out", 1, 2);
+       clks[IMX8MM_SYS_PLL2_1000M] = imx_clk_fixed_factor("sys_pll2_1000m", "sys_pll2_out", 1, 1);
+
+       np = ccm_node;
+       base = of_iomap(np, 0);
+       if (WARN_ON(!base))
+               return -ENOMEM;
+
+       /* Core Slice */
+       clks[IMX8MM_CLK_A53_SRC] = imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3, imx8mm_a53_sels, ARRAY_SIZE(imx8mm_a53_sels));
+       clks[IMX8MM_CLK_M4_SRC] = imx_clk_mux2("arm_m4_src", base + 0x8080, 24, 3, imx8mm_m4_sels, ARRAY_SIZE(imx8mm_m4_sels));
+       clks[IMX8MM_CLK_VPU_SRC] = imx_clk_mux2("vpu_src", base + 0x8100, 24, 3, imx8mm_vpu_sels, ARRAY_SIZE(imx8mm_vpu_sels));
+       clks[IMX8MM_CLK_GPU3D_SRC] = imx_clk_mux2("gpu3d_src", base + 0x8180, 24, 3,  imx8mm_gpu3d_sels, ARRAY_SIZE(imx8mm_gpu3d_sels));
+       clks[IMX8MM_CLK_GPU2D_SRC] = imx_clk_mux2("gpu2d_src", base + 0x8200, 24, 3, imx8mm_gpu2d_sels,  ARRAY_SIZE(imx8mm_gpu2d_sels));
+       clks[IMX8MM_CLK_A53_CG] = imx_clk_gate3("arm_a53_cg", "arm_a53_src", base + 0x8000, 28);
+       clks[IMX8MM_CLK_M4_CG] = imx_clk_gate3("arm_m4_cg", "arm_m4_src", base + 0x8080, 28);
+       clks[IMX8MM_CLK_VPU_CG] = imx_clk_gate3("vpu_cg", "vpu_src", base + 0x8100, 28);
+       clks[IMX8MM_CLK_GPU3D_CG] = imx_clk_gate3("gpu3d_cg", "gpu3d_src", base + 0x8180, 28);
+       clks[IMX8MM_CLK_GPU2D_CG] = imx_clk_gate3("gpu2d_cg", "gpu2d_src", base + 0x8200, 28);
+       clks[IMX8MM_CLK_A53_DIV] = imx_clk_divider2("arm_a53_div", "arm_a53_cg", base + 0x8000, 0, 3);
+       clks[IMX8MM_CLK_M4_DIV] = imx_clk_divider2("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3);
+       clks[IMX8MM_CLK_VPU_DIV] = imx_clk_divider2("vpu_div", "vpu_cg", base + 0x8100, 0, 3);
+       clks[IMX8MM_CLK_GPU3D_DIV] = imx_clk_divider2("gpu3d_div", "gpu3d_cg", base + 0x8180, 0, 3);
+       clks[IMX8MM_CLK_GPU2D_DIV] = imx_clk_divider2("gpu2d_div", "gpu2d_cg", base + 0x8200, 0, 3);
+
+       /* BUS */
+       clks[IMX8MM_CLK_MAIN_AXI] = imx8m_clk_composite_critical("main_axi",  imx8mm_main_axi_sels, base + 0x8800);
+       clks[IMX8MM_CLK_ENET_AXI] = imx8m_clk_composite("enet_axi", imx8mm_enet_axi_sels, base + 0x8880);
+       clks[IMX8MM_CLK_NAND_USDHC_BUS] = imx8m_clk_composite_critical("nand_usdhc_bus", imx8mm_nand_usdhc_sels, base + 0x8900);
+       clks[IMX8MM_CLK_VPU_BUS] = imx8m_clk_composite("vpu_bus", imx8mm_vpu_bus_sels, base + 0x8980);
+       clks[IMX8MM_CLK_DISP_AXI] = imx8m_clk_composite("disp_axi", imx8mm_disp_axi_sels, base + 0x8a00);
+       clks[IMX8MM_CLK_DISP_APB] = imx8m_clk_composite("disp_apb", imx8mm_disp_apb_sels, base + 0x8a80);
+       clks[IMX8MM_CLK_DISP_RTRM] = imx8m_clk_composite("disp_rtrm", imx8mm_disp_rtrm_sels, base + 0x8b00);
+       clks[IMX8MM_CLK_USB_BUS] = imx8m_clk_composite("usb_bus", imx8mm_usb_bus_sels, base + 0x8b80);
+       clks[IMX8MM_CLK_GPU_AXI] = imx8m_clk_composite("gpu_axi", imx8mm_gpu_axi_sels, base + 0x8c00);
+       clks[IMX8MM_CLK_GPU_AHB] = imx8m_clk_composite("gpu_ahb", imx8mm_gpu_ahb_sels, base + 0x8c80);
+       clks[IMX8MM_CLK_NOC] = imx8m_clk_composite_critical("noc", imx8mm_noc_sels, base + 0x8d00);
+       clks[IMX8MM_CLK_NOC_APB] = imx8m_clk_composite_critical("noc_apb", imx8mm_noc_apb_sels, base + 0x8d80);
+
+       /* AHB */
+       clks[IMX8MM_CLK_AHB] = imx8m_clk_composite_critical("ahb", imx8mm_ahb_sels, base + 0x9000);
+       clks[IMX8MM_CLK_AUDIO_AHB] = imx8m_clk_composite("audio_ahb", imx8mm_audio_ahb_sels, base + 0x9100);
+
+       /* IPG */
+       clks[IMX8MM_CLK_IPG_ROOT] = imx_clk_divider2("ipg_root", "ahb", base + 0x9080, 0, 1);
+       clks[IMX8MM_CLK_IPG_AUDIO_ROOT] = imx_clk_divider2("ipg_audio_root", "audio_ahb", base + 0x9180, 0, 1);
+
+       /* IP */
+       clks[IMX8MM_CLK_DRAM_ALT] = imx8m_clk_composite("dram_alt", imx8mm_dram_alt_sels, base + 0xa000);
+       clks[IMX8MM_CLK_DRAM_APB] = imx8m_clk_composite("dram_apb", imx8mm_dram_apb_sels, base + 0xa080);
+       clks[IMX8MM_CLK_VPU_G1] = imx8m_clk_composite("vpu_g1", imx8mm_vpu_g1_sels, base + 0xa100);
+       clks[IMX8MM_CLK_VPU_G2] = imx8m_clk_composite("vpu_g2", imx8mm_vpu_g2_sels, base + 0xa180);
+       clks[IMX8MM_CLK_DISP_DTRC] = imx8m_clk_composite("disp_dtrc", imx8mm_disp_dtrc_sels, base + 0xa200);
+       clks[IMX8MM_CLK_DISP_DC8000] = imx8m_clk_composite("disp_dc8000", imx8mm_disp_dc8000_sels, base + 0xa280);
+       clks[IMX8MM_CLK_PCIE1_CTRL] = imx8m_clk_composite("pcie1_ctrl", imx8mm_pcie1_ctrl_sels, base + 0xa300);
+       clks[IMX8MM_CLK_PCIE1_PHY] = imx8m_clk_composite("pcie1_phy", imx8mm_pcie1_phy_sels, base + 0xa380);
+       clks[IMX8MM_CLK_PCIE1_AUX] = imx8m_clk_composite("pcie1_aux", imx8mm_pcie1_aux_sels, base + 0xa400);
+       clks[IMX8MM_CLK_DC_PIXEL] = imx8m_clk_composite("dc_pixel", imx8mm_dc_pixel_sels, base + 0xa480);
+       clks[IMX8MM_CLK_LCDIF_PIXEL] = imx8m_clk_composite("lcdif_pixel", imx8mm_lcdif_pixel_sels, base + 0xa500);
+       clks[IMX8MM_CLK_SAI1] = imx8m_clk_composite("sai1", imx8mm_sai1_sels, base + 0xa580);
+       clks[IMX8MM_CLK_SAI2] = imx8m_clk_composite("sai2", imx8mm_sai2_sels, base + 0xa600);
+       clks[IMX8MM_CLK_SAI3] = imx8m_clk_composite("sai3", imx8mm_sai3_sels, base + 0xa680);
+       clks[IMX8MM_CLK_SAI4] = imx8m_clk_composite("sai4", imx8mm_sai4_sels, base + 0xa700);
+       clks[IMX8MM_CLK_SAI5] = imx8m_clk_composite("sai5", imx8mm_sai5_sels, base + 0xa780);
+       clks[IMX8MM_CLK_SAI6] = imx8m_clk_composite("sai6", imx8mm_sai6_sels, base + 0xa800);
+       clks[IMX8MM_CLK_SPDIF1] = imx8m_clk_composite("spdif1", imx8mm_spdif1_sels, base + 0xa880);
+       clks[IMX8MM_CLK_SPDIF2] = imx8m_clk_composite("spdif2", imx8mm_spdif2_sels, base + 0xa900);
+       clks[IMX8MM_CLK_ENET_REF] = imx8m_clk_composite("enet_ref", imx8mm_enet_ref_sels, base + 0xa980);
+       clks[IMX8MM_CLK_ENET_TIMER] = imx8m_clk_composite("enet_timer", imx8mm_enet_timer_sels, base + 0xaa00);
+       clks[IMX8MM_CLK_ENET_PHY_REF] = imx8m_clk_composite("enet_phy", imx8mm_enet_phy_sels, base + 0xaa80);
+       clks[IMX8MM_CLK_NAND] = imx8m_clk_composite("nand", imx8mm_nand_sels, base + 0xab00);
+       clks[IMX8MM_CLK_QSPI] = imx8m_clk_composite("qspi", imx8mm_qspi_sels, base + 0xab80);
+       clks[IMX8MM_CLK_USDHC1] = imx8m_clk_composite("usdhc1", imx8mm_usdhc1_sels, base + 0xac00);
+       clks[IMX8MM_CLK_USDHC2] = imx8m_clk_composite("usdhc2", imx8mm_usdhc2_sels, base + 0xac80);
+       clks[IMX8MM_CLK_I2C1] = imx8m_clk_composite("i2c1", imx8mm_i2c1_sels, base + 0xad00);
+       clks[IMX8MM_CLK_I2C2] = imx8m_clk_composite("i2c2", imx8mm_i2c2_sels, base + 0xad80);
+       clks[IMX8MM_CLK_I2C3] = imx8m_clk_composite("i2c3", imx8mm_i2c3_sels, base + 0xae00);
+       clks[IMX8MM_CLK_I2C4] = imx8m_clk_composite("i2c4", imx8mm_i2c4_sels, base + 0xae80);
+       clks[IMX8MM_CLK_UART1] = imx8m_clk_composite("uart1", imx8mm_uart1_sels, base + 0xaf00);
+       clks[IMX8MM_CLK_UART2] = imx8m_clk_composite("uart2", imx8mm_uart2_sels, base + 0xaf80);
+       clks[IMX8MM_CLK_UART3] = imx8m_clk_composite("uart3", imx8mm_uart3_sels, base + 0xb000);
+       clks[IMX8MM_CLK_UART4] = imx8m_clk_composite("uart4", imx8mm_uart4_sels, base + 0xb080);
+       clks[IMX8MM_CLK_USB_CORE_REF] = imx8m_clk_composite("usb_core_ref", imx8mm_usb_core_sels, base + 0xb100);
+       clks[IMX8MM_CLK_USB_PHY_REF] = imx8m_clk_composite("usb_phy_ref", imx8mm_usb_phy_sels, base + 0xb180);
+       clks[IMX8MM_CLK_ECSPI1] = imx8m_clk_composite("ecspi1", imx8mm_ecspi1_sels, base + 0xb280);
+       clks[IMX8MM_CLK_ECSPI2] = imx8m_clk_composite("ecspi2", imx8mm_ecspi2_sels, base + 0xb300);
+       clks[IMX8MM_CLK_PWM1] = imx8m_clk_composite("pwm1", imx8mm_pwm1_sels, base + 0xb380);
+       clks[IMX8MM_CLK_PWM2] = imx8m_clk_composite("pwm2", imx8mm_pwm2_sels, base + 0xb400);
+       clks[IMX8MM_CLK_PWM3] = imx8m_clk_composite("pwm3", imx8mm_pwm3_sels, base + 0xb480);
+       clks[IMX8MM_CLK_PWM4] = imx8m_clk_composite("pwm4", imx8mm_pwm4_sels, base + 0xb500);
+       clks[IMX8MM_CLK_GPT1] = imx8m_clk_composite("gpt1", imx8mm_gpt1_sels, base + 0xb580);
+       clks[IMX8MM_CLK_WDOG] = imx8m_clk_composite("wdog", imx8mm_wdog_sels, base + 0xb900);
+       clks[IMX8MM_CLK_WRCLK] = imx8m_clk_composite("wrclk", imx8mm_wrclk_sels, base + 0xb980);
+       clks[IMX8MM_CLK_CLKO1] = imx8m_clk_composite("clko1", imx8mm_clko1_sels, base + 0xba00);
+       clks[IMX8MM_CLK_DSI_CORE] = imx8m_clk_composite("dsi_core", imx8mm_dsi_core_sels, base + 0xbb00);
+       clks[IMX8MM_CLK_DSI_PHY_REF] = imx8m_clk_composite("dsi_phy_ref", imx8mm_dsi_phy_sels, base + 0xbb80);
+       clks[IMX8MM_CLK_DSI_DBI] = imx8m_clk_composite("dsi_dbi", imx8mm_dsi_dbi_sels, base + 0xbc00);
+       clks[IMX8MM_CLK_USDHC3] = imx8m_clk_composite("usdhc3", imx8mm_usdhc3_sels, base + 0xbc80);
+       clks[IMX8MM_CLK_CSI1_CORE] = imx8m_clk_composite("csi1_core", imx8mm_csi1_core_sels, base + 0xbd00);
+       clks[IMX8MM_CLK_CSI1_PHY_REF] = imx8m_clk_composite("csi1_phy_ref", imx8mm_csi1_phy_sels, base + 0xbd80);
+       clks[IMX8MM_CLK_CSI1_ESC] = imx8m_clk_composite("csi1_esc", imx8mm_csi1_esc_sels, base + 0xbe00);
+       clks[IMX8MM_CLK_CSI2_CORE] = imx8m_clk_composite("csi2_core", imx8mm_csi2_core_sels, base + 0xbe80);
+       clks[IMX8MM_CLK_CSI2_PHY_REF] = imx8m_clk_composite("csi2_phy_ref", imx8mm_csi2_phy_sels, base + 0xbf00);
+       clks[IMX8MM_CLK_CSI2_ESC] = imx8m_clk_composite("csi2_esc", imx8mm_csi2_esc_sels, base + 0xbf80);
+       clks[IMX8MM_CLK_PCIE2_CTRL] = imx8m_clk_composite("pcie2_ctrl", imx8mm_pcie2_ctrl_sels, base + 0xc000);
+       clks[IMX8MM_CLK_PCIE2_PHY] = imx8m_clk_composite("pcie2_phy", imx8mm_pcie2_phy_sels, base + 0xc080);
+       clks[IMX8MM_CLK_PCIE2_AUX] = imx8m_clk_composite("pcie2_aux", imx8mm_pcie2_aux_sels, base + 0xc100);
+       clks[IMX8MM_CLK_ECSPI3] = imx8m_clk_composite("ecspi3", imx8mm_ecspi3_sels, base + 0xc180);
+       clks[IMX8MM_CLK_PDM] = imx8m_clk_composite("pdm", imx8mm_pdm_sels, base + 0xc200);
+       clks[IMX8MM_CLK_VPU_H1] = imx8m_clk_composite("vpu_h1", imx8mm_vpu_h1_sels, base + 0xc280);
+
+       /* CCGR */
+       clks[IMX8MM_CLK_ECSPI1_ROOT] = imx_clk_gate4("ecspi1_root_clk", "ecspi1", base + 0x4070, 0);
+       clks[IMX8MM_CLK_ECSPI2_ROOT] = imx_clk_gate4("ecspi2_root_clk", "ecspi2", base + 0x4080, 0);
+       clks[IMX8MM_CLK_ECSPI3_ROOT] = imx_clk_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090, 0);
+       clks[IMX8MM_CLK_ENET1_ROOT] = imx_clk_gate4("enet1_root_clk", "enet_axi", base + 0x40a0, 0);
+       clks[IMX8MM_CLK_GPT1_ROOT] = imx_clk_gate4("gpt1_root_clk", "gpt1", base + 0x4100, 0);
+       clks[IMX8MM_CLK_I2C1_ROOT] = imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0);
+       clks[IMX8MM_CLK_I2C2_ROOT] = imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0);
+       clks[IMX8MM_CLK_I2C3_ROOT] = imx_clk_gate4("i2c3_root_clk", "i2c3", base + 0x4190, 0);
+       clks[IMX8MM_CLK_I2C4_ROOT] = imx_clk_gate4("i2c4_root_clk", "i2c4", base + 0x41a0, 0);
+       clks[IMX8MM_CLK_MU_ROOT] = imx_clk_gate4("mu_root_clk", "ipg_root", base + 0x4210, 0);
+       clks[IMX8MM_CLK_OCOTP_ROOT] = imx_clk_gate4("ocotp_root_clk", "ipg_root", base + 0x4220, 0);
+       clks[IMX8MM_CLK_PCIE1_ROOT] = imx_clk_gate4("pcie1_root_clk", "pcie1_ctrl", base + 0x4250, 0);
+       clks[IMX8MM_CLK_PWM1_ROOT] = imx_clk_gate4("pwm1_root_clk", "pwm1", base + 0x4280, 0);
+       clks[IMX8MM_CLK_PWM2_ROOT] = imx_clk_gate4("pwm2_root_clk", "pwm2", base + 0x4290, 0);
+       clks[IMX8MM_CLK_PWM3_ROOT] = imx_clk_gate4("pwm3_root_clk", "pwm3", base + 0x42a0, 0);
+       clks[IMX8MM_CLK_PWM4_ROOT] = imx_clk_gate4("pwm4_root_clk", "pwm4", base + 0x42b0, 0);
+       clks[IMX8MM_CLK_QSPI_ROOT] = imx_clk_gate4("qspi_root_clk", "qspi", base + 0x42f0, 0);
+       clks[IMX8MM_CLK_NAND_ROOT] = imx_clk_gate2_shared2("nand_root_clk", "nand", base + 0x4300, 0, &share_count_nand);
+       clks[IMX8MM_CLK_NAND_USDHC_BUS_RAWNAND_CLK] = imx_clk_gate2_shared2("nand_usdhc_rawnand_clk", "nand_usdhc_bus", base + 0x4300, 0, &share_count_nand);
+       clks[IMX8MM_CLK_SAI1_ROOT] = imx_clk_gate2_shared2("sai1_root_clk", "sai1", base + 0x4330, 0, &share_count_sai1);
+       clks[IMX8MM_CLK_SAI1_IPG] = imx_clk_gate2_shared2("sai1_ipg_clk", "ipg_audio_root", base + 0x4330, 0, &share_count_sai1);
+       clks[IMX8MM_CLK_SAI2_ROOT] = imx_clk_gate2_shared2("sai2_root_clk", "sai2", base + 0x4340, 0, &share_count_sai2);
+       clks[IMX8MM_CLK_SAI2_IPG] = imx_clk_gate2_shared2("sai2_ipg_clk", "ipg_audio_root", base + 0x4340, 0, &share_count_sai2);
+       clks[IMX8MM_CLK_SAI3_ROOT] = imx_clk_gate2_shared2("sai3_root_clk", "sai3", base + 0x4350, 0, &share_count_sai3);
+       clks[IMX8MM_CLK_SAI3_IPG] = imx_clk_gate2_shared2("sai3_ipg_clk", "ipg_audio_root", base + 0x4350, 0, &share_count_sai3);
+       clks[IMX8MM_CLK_SAI4_ROOT] = imx_clk_gate2_shared2("sai4_root_clk", "sai4", base + 0x4360, 0, &share_count_sai4);
+       clks[IMX8MM_CLK_SAI4_IPG] = imx_clk_gate2_shared2("sai4_ipg_clk", "ipg_audio_root", base + 0x4360, 0, &share_count_sai4);
+       clks[IMX8MM_CLK_SAI5_ROOT] = imx_clk_gate2_shared2("sai5_root_clk", "sai5", base + 0x4370, 0, &share_count_sai5);
+       clks[IMX8MM_CLK_SAI5_IPG] = imx_clk_gate2_shared2("sai5_ipg_clk", "ipg_audio_root", base + 0x4370, 0, &share_count_sai5);
+       clks[IMX8MM_CLK_SAI6_ROOT] = imx_clk_gate2_shared2("sai6_root_clk", "sai6", base + 0x4380, 0, &share_count_sai6);
+       clks[IMX8MM_CLK_SAI6_IPG] = imx_clk_gate2_shared2("sai6_ipg_clk", "ipg_audio_root", base + 0x4380, 0, &share_count_sai6);
+       clks[IMX8MM_CLK_UART1_ROOT] = imx_clk_gate4("uart1_root_clk", "uart1", base + 0x4490, 0);
+       clks[IMX8MM_CLK_UART2_ROOT] = imx_clk_gate4("uart2_root_clk", "uart2", base + 0x44a0, 0);
+       clks[IMX8MM_CLK_UART3_ROOT] = imx_clk_gate4("uart3_root_clk", "uart3", base + 0x44b0, 0);
+       clks[IMX8MM_CLK_UART4_ROOT] = imx_clk_gate4("uart4_root_clk", "uart4", base + 0x44c0, 0);
+       clks[IMX8MM_CLK_USB1_CTRL_ROOT] = imx_clk_gate4("usb1_ctrl_root_clk", "usb_core_ref", base + 0x44d0, 0);
+       clks[IMX8MM_CLK_GPU3D_ROOT] = imx_clk_gate4("gpu3d_root_clk", "gpu3d_div", base + 0x44f0, 0);
+       clks[IMX8MM_CLK_USDHC1_ROOT] = imx_clk_gate4("usdhc1_root_clk", "usdhc1", base + 0x4510, 0);
+       clks[IMX8MM_CLK_USDHC2_ROOT] = imx_clk_gate4("usdhc2_root_clk", "usdhc2", base + 0x4520, 0);
+       clks[IMX8MM_CLK_WDOG1_ROOT] = imx_clk_gate4("wdog1_root_clk", "wdog", base + 0x4530, 0);
+       clks[IMX8MM_CLK_WDOG2_ROOT] = imx_clk_gate4("wdog2_root_clk", "wdog", base + 0x4540, 0);
+       clks[IMX8MM_CLK_WDOG3_ROOT] = imx_clk_gate4("wdog3_root_clk", "wdog", base + 0x4550, 0);
+       clks[IMX8MM_CLK_VPU_G1_ROOT] = imx_clk_gate4("vpu_g1_root_clk", "vpu_g1", base + 0x4560, 0);
+       clks[IMX8MM_CLK_GPU_BUS_ROOT] = imx_clk_gate4("gpu_root_clk", "gpu_axi", base + 0x4570, 0);
+       clks[IMX8MM_CLK_VPU_H1_ROOT] = imx_clk_gate4("vpu_h1_root_clk", "vpu_h1", base + 0x4590, 0);
+       clks[IMX8MM_CLK_VPU_G2_ROOT] = imx_clk_gate4("vpu_g2_root_clk", "vpu_g2", base + 0x45a0, 0);
+       clks[IMX8MM_CLK_PDM_ROOT] = imx_clk_gate2_shared2("pdm_root_clk", "pdm", base + 0x45b0, 0, &share_count_pdm);
+       clks[IMX8MM_CLK_PDM_IPG]  = imx_clk_gate2_shared2("pdm_ipg_clk", "ipg_audio_root", base + 0x45b0, 0, &share_count_pdm);
+       clks[IMX8MM_CLK_DISP_ROOT] = imx_clk_gate2_shared2("disp_root_clk", "disp_dc8000", base + 0x45d0, 0, &share_count_dcss);
+       clks[IMX8MM_CLK_DISP_AXI_ROOT]  = imx_clk_gate2_shared2("disp_axi_root_clk", "disp_axi", base + 0x45d0, 0, &share_count_dcss);
+       clks[IMX8MM_CLK_DISP_APB_ROOT]  = imx_clk_gate2_shared2("disp_apb_root_clk", "disp_apb", base + 0x45d0, 0, &share_count_dcss);
+       clks[IMX8MM_CLK_DISP_RTRM_ROOT] = imx_clk_gate2_shared2("disp_rtrm_root_clk", "disp_rtrm", base + 0x45d0, 0, &share_count_dcss);
+       clks[IMX8MM_CLK_USDHC3_ROOT] = imx_clk_gate4("usdhc3_root_clk", "usdhc3", base + 0x45e0, 0);
+       clks[IMX8MM_CLK_TMU_ROOT] = imx_clk_gate4("tmu_root_clk", "ipg_root", base + 0x4620, 0);
+       clks[IMX8MM_CLK_VPU_DEC_ROOT] = imx_clk_gate4("vpu_dec_root_clk", "vpu_bus", base + 0x4630, 0);
+       clks[IMX8MM_CLK_SDMA1_ROOT] = imx_clk_gate4("sdma1_clk", "ipg_root", base + 0x43a0, 0);
+       clks[IMX8MM_CLK_SDMA2_ROOT] = imx_clk_gate4("sdma2_clk", "ipg_audio_root", base + 0x43b0, 0);
+       clks[IMX8MM_CLK_SDMA3_ROOT] = imx_clk_gate4("sdma3_clk", "ipg_audio_root", base + 0x45f0, 0);
+       clks[IMX8MM_CLK_GPU2D_ROOT] = imx_clk_gate4("gpu2d_root_clk", "gpu2d_div", base + 0x4660, 0);
+       clks[IMX8MM_CLK_CSI1_ROOT] = imx_clk_gate4("csi1_root_clk", "csi1_core", base + 0x4650, 0);
+
+       clks[IMX8MM_CLK_GPT_3M] = imx_clk_fixed_factor("gpt_3m", "osc_24m", 1, 8);
+
+       clks[IMX8MM_CLK_DRAM_ALT_ROOT] = imx_clk_fixed_factor("dram_alt_root", "dram_alt", 1, 4);
+       clks[IMX8MM_CLK_DRAM_CORE] = imx_clk_mux2_flags("dram_core_clk", base + 0x9800, 24, 1, imx8mm_dram_core_sels, ARRAY_SIZE(imx8mm_dram_core_sels), CLK_IS_CRITICAL);
+
+       clks[IMX8MM_CLK_ARM] = imx_clk_cpu("arm", "arm_a53_div",
+                                          clks[IMX8MM_CLK_A53_DIV],
+                                          clks[IMX8MM_CLK_A53_SRC],
+                                          clks[IMX8MM_ARM_PLL_OUT],
+                                          clks[IMX8MM_CLK_24M]);
+
+       imx_check_clocks(clks, ARRAY_SIZE(clks));
+
+       clk_data.clks = clks;
+       clk_data.clk_num = ARRAY_SIZE(clks);
+       ret = of_clk_add_provider(np, of_clk_src_onecell_get, &clk_data);
+       if (ret < 0) {
+               pr_err("failed to register clks for i.MX8MM\n");
+               return -EINVAL;
+       }
+
+       imx_register_uart_clocks(uart_clks);
+
+       return 0;
+}
+CLK_OF_DECLARE_DRIVER(imx8mm, "fsl,imx8mm-ccm", imx8mm_clocks_init);
index 26b57f4..a9b3888 100644 (file)
@@ -26,246 +26,246 @@ static u32 share_count_nand;
 
 static struct clk *clks[IMX8MQ_CLK_END];
 
-static const char *pll_ref_sels[] = { "osc_25m", "osc_27m", "dummy", "dummy", };
-static const char *arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
-static const char *gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
-static const char *vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
-static const char *audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
-static const char *audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
-static const char *video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", };
-
-static const char *sys1_pll1_out_sels[] = {"sys1_pll1", "sys1_pll1_ref_sel", };
-static const char *sys2_pll1_out_sels[] = {"sys2_pll1", "sys1_pll1_ref_sel", };
-static const char *sys3_pll1_out_sels[] = {"sys3_pll1", "sys3_pll1_ref_sel", };
-static const char *dram_pll1_out_sels[] = {"dram_pll1", "dram_pll1_ref_sel", };
-
-static const char *sys1_pll2_out_sels[] = {"sys1_pll2_div", "sys1_pll1_ref_sel", };
-static const char *sys2_pll2_out_sels[] = {"sys2_pll2_div", "sys2_pll1_ref_sel", };
-static const char *sys3_pll2_out_sels[] = {"sys3_pll2_div", "sys2_pll1_ref_sel", };
-static const char *dram_pll2_out_sels[] = {"dram_pll2_div", "dram_pll1_ref_sel", };
+static const char * const pll_ref_sels[] = { "osc_25m", "osc_27m", "dummy", "dummy", };
+static const char * const arm_pll_bypass_sels[] = {"arm_pll", "arm_pll_ref_sel", };
+static const char * const gpu_pll_bypass_sels[] = {"gpu_pll", "gpu_pll_ref_sel", };
+static const char * const vpu_pll_bypass_sels[] = {"vpu_pll", "vpu_pll_ref_sel", };
+static const char * const audio_pll1_bypass_sels[] = {"audio_pll1", "audio_pll1_ref_sel", };
+static const char * const audio_pll2_bypass_sels[] = {"audio_pll2", "audio_pll2_ref_sel", };
+static const char * const video_pll1_bypass_sels[] = {"video_pll1", "video_pll1_ref_sel", };
+
+static const char * const sys1_pll_out_sels[] = {"sys1_pll1_ref_sel", };
+static const char * const sys2_pll_out_sels[] = {"sys1_pll1_ref_sel", "sys2_pll1_ref_sel", };
+static const char * const sys3_pll_out_sels[] = {"sys3_pll1_ref_sel", "sys2_pll1_ref_sel", };
+static const char * const dram_pll_out_sels[] = {"dram_pll1_ref_sel", };
 
 /* CCM ROOT */
-static const char *imx8mq_a53_sels[] = {"osc_25m", "arm_pll_out", "sys2_pll_500m", "sys2_pll_1000m",
+static const char * const imx8mq_a53_sels[] = {"osc_25m", "arm_pll_out", "sys2_pll_500m", "sys2_pll_1000m",
                                        "sys1_pll_800m", "sys1_pll_400m", "audio_pll1_out", "sys3_pll2_out", };
 
-static const char *imx8mq_vpu_sels[] = {"osc_25m", "arm_pll_out", "sys2_pll_500m", "sys2_pll_1000m",
+static const char * const imx8mq_arm_m4_sels[] = {"osc_25m", "sys2_pll_200m", "sys2_pll_250m", "sys1_pll_266m",
+                                       "sys1_pll_800m", "audio_pll1_out", "video_pll1_out", "sys3_pll2_out", };
+
+static const char * const imx8mq_vpu_sels[] = {"osc_25m", "arm_pll_out", "sys2_pll_500m", "sys2_pll_1000m",
                                        "sys1_pll_800m", "sys1_pll_400m", "audio_pll1_out", "vpu_pll_out", };
 
-static const char *imx8mq_gpu_core_sels[] = {"osc_25m", "gpu_pll_out", "sys1_pll_800m", "sys3_pll2_out",
+static const char * const imx8mq_gpu_core_sels[] = {"osc_25m", "gpu_pll_out", "sys1_pll_800m", "sys3_pll2_out",
                                             "sys2_pll_1000m", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
 
-static const char *imx8mq_gpu_shader_sels[] = {"osc_25m", "gpu_pll_out", "sys1_pll_800m", "sys3_pll2_out",
+static const char * const imx8mq_gpu_shader_sels[] = {"osc_25m", "gpu_pll_out", "sys1_pll_800m", "sys3_pll2_out",
                                               "sys2_pll_1000m", "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
 
-static const char *imx8mq_main_axi_sels[] = {"osc_25m", "sys2_pll_333m", "sys1_pll_800m", "sys2_pll_250m",
+static const char * const imx8mq_main_axi_sels[] = {"osc_25m", "sys2_pll_333m", "sys1_pll_800m", "sys2_pll_250m",
                                             "sys2_pll_1000m", "audio_pll1_out", "video_pll1_out", "sys1_pll_100m",};
 
-static const char *imx8mq_enet_axi_sels[] = {"osc_25m", "sys1_pll_266m", "sys1_pll_800m", "sys2_pll_250m",
+static const char * const imx8mq_enet_axi_sels[] = {"osc_25m", "sys1_pll_266m", "sys1_pll_800m", "sys2_pll_250m",
                                             "sys2_pll_200m", "audio_pll1_out", "video_pll1_out", "sys3_pll2_out", };
 
-static const char *imx8mq_nand_usdhc_sels[] = {"osc_25m", "sys1_pll_266m", "sys1_pll_800m", "sys2_pll_200m",
+static const char * const imx8mq_nand_usdhc_sels[] = {"osc_25m", "sys1_pll_266m", "sys1_pll_800m", "sys2_pll_200m",
                                               "sys1_pll_133m", "sys3_pll2_out", "sys2_pll_250m", "audio_pll1_out", };
 
-static const char *imx8mq_vpu_bus_sels[] = {"osc_25m", "sys1_pll_800m", "vpu_pll_out", "audio_pll2_out", "sys3_pll2_out", "sys2_pll_1000m", "sys2_pll_200m", "sys1_pll_100m", };
+static const char * const imx8mq_vpu_bus_sels[] = {"osc_25m", "sys1_pll_800m", "vpu_pll_out", "audio_pll2_out", "sys3_pll2_out", "sys2_pll_1000m", "sys2_pll_200m", "sys1_pll_100m", };
 
-static const char *imx8mq_disp_axi_sels[] = {"osc_25m", "sys2_pll_125m", "sys1_pll_800m", "sys3_pll2_out", "sys1_pll_400m", "audio_pll2_out", "clk_ext1", "clk_ext4", };
+static const char * const imx8mq_disp_axi_sels[] = {"osc_25m", "sys2_pll_125m", "sys1_pll_800m", "sys3_pll2_out", "sys1_pll_400m", "audio_pll2_out", "clk_ext1", "clk_ext4", };
 
-static const char *imx8mq_disp_apb_sels[] = {"osc_25m", "sys2_pll_125m", "sys1_pll_800m", "sys3_pll2_out",
+static const char * const imx8mq_disp_apb_sels[] = {"osc_25m", "sys2_pll_125m", "sys1_pll_800m", "sys3_pll2_out",
                                             "sys1_pll_40m", "audio_pll2_out", "clk_ext1", "clk_ext3", };
 
-static const char *imx8mq_disp_rtrm_sels[] = {"osc_25m", "sys1_pll_800m", "sys2_pll_200m", "sys1_pll_400m",
+static const char * const imx8mq_disp_rtrm_sels[] = {"osc_25m", "sys1_pll_800m", "sys2_pll_200m", "sys1_pll_400m",
                                              "audio_pll1_out", "video_pll1_out", "clk_ext2", "clk_ext3", };
 
-static const char *imx8mq_usb_bus_sels[] = {"osc_25m", "sys2_pll_500m", "sys1_pll_800m", "sys2_pll_100m",
+static const char * const imx8mq_usb_bus_sels[] = {"osc_25m", "sys2_pll_500m", "sys1_pll_800m", "sys2_pll_100m",
                                            "sys2_pll_200m", "clk_ext2", "clk_ext4", "audio_pll2_out", };
 
-static const char *imx8mq_gpu_axi_sels[] = {"osc_25m", "sys1_pll_800m", "gpu_pll_out", "sys3_pll2_out", "sys2_pll_1000m",
+static const char * const imx8mq_gpu_axi_sels[] = {"osc_25m", "sys1_pll_800m", "gpu_pll_out", "sys3_pll2_out", "sys2_pll_1000m",
                                            "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
 
-static const char *imx8mq_gpu_ahb_sels[] = {"osc_25m", "sys1_pll_800m", "gpu_pll_out", "sys3_pll2_out", "sys2_pll_1000m",
+static const char * const imx8mq_gpu_ahb_sels[] = {"osc_25m", "sys1_pll_800m", "gpu_pll_out", "sys3_pll2_out", "sys2_pll_1000m",
                                            "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
 
-static const char *imx8mq_noc_sels[] = {"osc_25m", "sys1_pll_800m", "sys3_pll2_out", "sys2_pll_1000m", "sys2_pll_500m",
+static const char * const imx8mq_noc_sels[] = {"osc_25m", "sys1_pll_800m", "sys3_pll2_out", "sys2_pll_1000m", "sys2_pll_500m",
                                        "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
 
-static const char *imx8mq_noc_apb_sels[] = {"osc_25m", "sys1_pll_400m", "sys3_pll2_out", "sys2_pll_333m", "sys2_pll_200m",
+static const char * const imx8mq_noc_apb_sels[] = {"osc_25m", "sys1_pll_400m", "sys3_pll2_out", "sys2_pll_333m", "sys2_pll_200m",
                                            "sys1_pll_800m", "audio_pll1_out", "video_pll1_out", };
 
-static const char *imx8mq_ahb_sels[] = {"osc_25m", "sys1_pll_133m", "sys1_pll_800m", "sys1_pll_400m",
+static const char * const imx8mq_ahb_sels[] = {"osc_25m", "sys1_pll_133m", "sys1_pll_800m", "sys1_pll_400m",
                                        "sys2_pll_125m", "sys3_pll2_out", "audio_pll1_out", "video_pll1_out", };
 
-static const char *imx8mq_audio_ahb_sels[] = {"osc_25m", "sys2_pll_500m", "sys1_pll_800m", "sys2_pll_1000m",
+static const char * const imx8mq_audio_ahb_sels[] = {"osc_25m", "sys2_pll_500m", "sys1_pll_800m", "sys2_pll_1000m",
                                                  "sys2_pll_166m", "sys3_pll2_out", "audio_pll1_out", "video_pll1_out", };
 
-static const char *imx8mq_dsi_ahb_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m",
+static const char * const imx8mq_dsi_ahb_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m",
                                                "sys2_pll_1000m", "sys3_pll2_out", "clk_ext3", "audio_pll2_out"};
 
-static const char *imx8mq_dram_alt_sels[] = {"osc_25m", "sys1_pll_800m", "sys1_pll_100m", "sys2_pll_500m",
+static const char * const imx8mq_dram_alt_sels[] = {"osc_25m", "sys1_pll_800m", "sys1_pll_100m", "sys2_pll_500m",
                                                "sys2_pll_250m", "sys1_pll_400m", "audio_pll1_out", "sys1_pll_266m", };
 
-static const char *imx8mq_dram_apb_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_40m", "sys1_pll_160m",
+static const char * const imx8mq_dram_apb_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_40m", "sys1_pll_160m",
                                                "sys1_pll_800m", "sys3_pll2_out", "sys2_pll_250m", "audio_pll2_out", };
 
-static const char *imx8mq_vpu_g1_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_100m", "sys2_pll_125m", "sys3_pll2_out", "audio_pll1_out", };
+static const char * const imx8mq_vpu_g1_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_100m", "sys2_pll_125m", "sys3_pll2_out", "audio_pll1_out", };
 
-static const char *imx8mq_vpu_g2_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_100m", "sys2_pll_125m", "sys3_pll2_out", "audio_pll1_out", };
+static const char * const imx8mq_vpu_g2_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_100m", "sys2_pll_125m", "sys3_pll2_out", "audio_pll1_out", };
 
-static const char *imx8mq_disp_dtrc_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_160m", "sys2_pll_100m", "sys3_pll2_out", "audio_pll2_out", };
+static const char * const imx8mq_disp_dtrc_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_160m", "sys2_pll_100m", "sys3_pll2_out", "audio_pll2_out", };
 
-static const char *imx8mq_disp_dc8000_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_160m", "sys2_pll_100m", "sys3_pll2_out", "audio_pll2_out", };
+static const char * const imx8mq_disp_dc8000_sels[] = {"osc_25m", "vpu_pll_out", "sys1_pll_800m", "sys2_pll_1000m", "sys1_pll_160m", "sys2_pll_100m", "sys3_pll2_out", "audio_pll2_out", };
 
-static const char *imx8mq_pcie1_ctrl_sels[] = {"osc_25m", "sys2_pll_250m", "sys2_pll_200m", "sys1_pll_266m",
+static const char * const imx8mq_pcie1_ctrl_sels[] = {"osc_25m", "sys2_pll_250m", "sys2_pll_200m", "sys1_pll_266m",
                                               "sys1_pll_800m", "sys2_pll_500m", "sys2_pll_250m", "sys3_pll2_out", };
 
-static const char *imx8mq_pcie1_phy_sels[] = {"osc_25m", "sys2_pll_100m", "sys2_pll_500m", "clk_ext1", "clk_ext2",
+static const char * const imx8mq_pcie1_phy_sels[] = {"osc_25m", "sys2_pll_100m", "sys2_pll_500m", "clk_ext1", "clk_ext2",
                                              "clk_ext3", "clk_ext4", };
 
-static const char *imx8mq_pcie1_aux_sels[] = {"osc_25m", "sys2_pll_200m", "sys2_pll_500m", "sys3_pll2_out",
+static const char * const imx8mq_pcie1_aux_sels[] = {"osc_25m", "sys2_pll_200m", "sys2_pll_500m", "sys3_pll2_out",
                                              "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_160m", "sys1_pll_200m", };
 
-static const char *imx8mq_dc_pixel_sels[] = {"osc_25m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out", "sys1_pll_800m", "sys2_pll_1000m", "sys3_pll2_out", "clk_ext4", };
+static const char * const imx8mq_dc_pixel_sels[] = {"osc_25m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out", "sys1_pll_800m", "sys2_pll_1000m", "sys3_pll2_out", "clk_ext4", };
 
-static const char *imx8mq_lcdif_pixel_sels[] = {"osc_25m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out", "sys1_pll_800m", "sys2_pll_1000m", "sys3_pll2_out", "clk_ext4", };
+static const char * const imx8mq_lcdif_pixel_sels[] = {"osc_25m", "video_pll1_out", "audio_pll2_out", "audio_pll1_out", "sys1_pll_800m", "sys2_pll_1000m", "sys3_pll2_out", "clk_ext4", };
 
-static const char *imx8mq_sai1_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext1", "clk_ext2", };
+static const char * const imx8mq_sai1_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext1", "clk_ext2", };
 
-static const char *imx8mq_sai2_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext2", "clk_ext3", };
+static const char * const imx8mq_sai2_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext2", "clk_ext3", };
 
-static const char *imx8mq_sai3_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext3", "clk_ext4", };
+static const char * const imx8mq_sai3_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext3", "clk_ext4", };
 
-static const char *imx8mq_sai4_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext1", "clk_ext2", };
+static const char * const imx8mq_sai4_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext1", "clk_ext2", };
 
-static const char *imx8mq_sai5_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext2", "clk_ext3", };
+static const char * const imx8mq_sai5_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext2", "clk_ext3", };
 
-static const char *imx8mq_sai6_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext3", "clk_ext4", };
+static const char * const imx8mq_sai6_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext3", "clk_ext4", };
 
-static const char *imx8mq_spdif1_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext2", "clk_ext3", };
+static const char * const imx8mq_spdif1_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext2", "clk_ext3", };
 
-static const char *imx8mq_spdif2_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext3", "clk_ext4", };
+static const char * const imx8mq_spdif2_sels[] = {"osc_25m", "audio_pll1_out", "audio_pll2_out", "video_pll1_out", "sys1_pll_133m", "osc_27m", "clk_ext3", "clk_ext4", };
 
-static const char *imx8mq_enet_ref_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_500m", "sys2_pll_100m",
+static const char * const imx8mq_enet_ref_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_500m", "sys2_pll_100m",
                                             "sys1_pll_160m", "audio_pll1_out", "video_pll1_out", "clk_ext4", };
 
-static const char *imx8mq_enet_timer_sels[] = {"osc_25m", "sys2_pll_100m", "audio_pll1_out", "clk_ext1", "clk_ext2",
+static const char * const imx8mq_enet_timer_sels[] = {"osc_25m", "sys2_pll_100m", "audio_pll1_out", "clk_ext1", "clk_ext2",
                                               "clk_ext3", "clk_ext4", "video_pll1_out", };
 
-static const char *imx8mq_enet_phy_sels[] = {"osc_25m", "sys2_pll_50m", "sys2_pll_125m", "sys2_pll_500m",
+static const char * const imx8mq_enet_phy_sels[] = {"osc_25m", "sys2_pll_50m", "sys2_pll_125m", "sys2_pll_500m",
                                             "audio_pll1_out", "video_pll1_out", "audio_pll2_out", };
 
-static const char *imx8mq_nand_sels[] = {"osc_25m", "sys2_pll_500m", "audio_pll1_out", "sys1_pll_400m",
+static const char * const imx8mq_nand_sels[] = {"osc_25m", "sys2_pll_500m", "audio_pll1_out", "sys1_pll_400m",
                                         "audio_pll2_out", "sys3_pll2_out", "sys2_pll_250m", "video_pll1_out", };
 
-static const char *imx8mq_qspi_sels[] = {"osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m",
+static const char * const imx8mq_qspi_sels[] = {"osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m",
                                         "audio_pll2_out", "sys1_pll_266m", "sys3_pll2_out", "sys1_pll_100m", };
 
-static const char *imx8mq_usdhc1_sels[] = {"osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m",
+static const char * const imx8mq_usdhc1_sels[] = {"osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m",
                                         "audio_pll2_out", "sys1_pll_266m", "sys3_pll2_out", "sys1_pll_100m", };
 
-static const char *imx8mq_usdhc2_sels[] = {"osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m",
+static const char * const imx8mq_usdhc2_sels[] = {"osc_25m", "sys1_pll_400m", "sys1_pll_800m", "sys2_pll_500m",
                                         "audio_pll2_out", "sys1_pll_266m", "sys3_pll2_out", "sys1_pll_100m", };
 
-static const char *imx8mq_i2c1_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll2_out", "audio_pll1_out",
+static const char * const imx8mq_i2c1_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll2_out", "audio_pll1_out",
                                         "video_pll1_out", "audio_pll2_out", "sys1_pll_133m", };
 
-static const char *imx8mq_i2c2_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll2_out", "audio_pll1_out",
+static const char * const imx8mq_i2c2_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll2_out", "audio_pll1_out",
                                         "video_pll1_out", "audio_pll2_out", "sys1_pll_133m", };
 
-static const char *imx8mq_i2c3_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll2_out", "audio_pll1_out",
+static const char * const imx8mq_i2c3_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll2_out", "audio_pll1_out",
                                         "video_pll1_out", "audio_pll2_out", "sys1_pll_133m", };
 
-static const char *imx8mq_i2c4_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll2_out", "audio_pll1_out",
+static const char * const imx8mq_i2c4_sels[] = {"osc_25m", "sys1_pll_160m", "sys2_pll_50m", "sys3_pll2_out", "audio_pll1_out",
                                         "video_pll1_out", "audio_pll2_out", "sys1_pll_133m", };
 
-static const char *imx8mq_uart1_sels[] = {"osc_25m", "sys1_pll_80m", "sys2_pll_200m", "sys2_pll_100m",
+static const char * const imx8mq_uart1_sels[] = {"osc_25m", "sys1_pll_80m", "sys2_pll_200m", "sys2_pll_100m",
                                          "sys3_pll2_out", "clk_ext2", "clk_ext4", "audio_pll2_out", };
 
-static const char *imx8mq_uart2_sels[] = {"osc_25m", "sys1_pll_80m", "sys2_pll_200m", "sys2_pll_100m",
+static const char * const imx8mq_uart2_sels[] = {"osc_25m", "sys1_pll_80m", "sys2_pll_200m", "sys2_pll_100m",
                                          "sys3_pll2_out", "clk_ext2", "clk_ext3", "audio_pll2_out", };
 
-static const char *imx8mq_uart3_sels[] = {"osc_25m", "sys1_pll_80m", "sys2_pll_200m", "sys2_pll_100m",
+static const char * const imx8mq_uart3_sels[] = {"osc_25m", "sys1_pll_80m", "sys2_pll_200m", "sys2_pll_100m",
                                          "sys3_pll2_out", "clk_ext2", "clk_ext4", "audio_pll2_out", };
 
-static const char *imx8mq_uart4_sels[] = {"osc_25m", "sys1_pll_80m", "sys2_pll_200m", "sys2_pll_100m",
+static const char * const imx8mq_uart4_sels[] = {"osc_25m", "sys1_pll_80m", "sys2_pll_200m", "sys2_pll_100m",
                                          "sys3_pll2_out", "clk_ext2", "clk_ext3", "audio_pll2_out", };
 
-static const char *imx8mq_usb_core_sels[] = {"osc_25m", "sys1_pll_100m", "sys1_pll_40m", "sys2_pll_100m",
+static const char * const imx8mq_usb_core_sels[] = {"osc_25m", "sys1_pll_100m", "sys1_pll_40m", "sys2_pll_100m",
                                             "sys2_pll_200m", "clk_ext2", "clk_ext3", "audio_pll2_out", };
 
-static const char *imx8mq_usb_phy_sels[] = {"osc_25m", "sys1_pll_100m", "sys1_pll_40m", "sys2_pll_100m",
+static const char * const imx8mq_usb_phy_sels[] = {"osc_25m", "sys1_pll_100m", "sys1_pll_40m", "sys2_pll_100m",
                                             "sys2_pll_200m", "clk_ext2", "clk_ext3", "audio_pll2_out", };
 
-static const char *imx8mq_ecspi1_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_40m", "sys1_pll_160m",
+static const char * const imx8mq_ecspi1_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_40m", "sys1_pll_160m",
                                           "sys1_pll_800m", "sys3_pll2_out", "sys2_pll_250m", "audio_pll2_out", };
 
-static const char *imx8mq_ecspi2_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_40m", "sys1_pll_160m",
+static const char * const imx8mq_ecspi2_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_40m", "sys1_pll_160m",
                                           "sys1_pll_800m", "sys3_pll2_out", "sys2_pll_250m", "audio_pll2_out", };
 
-static const char *imx8mq_pwm1_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_160m", "sys1_pll_40m",
+static const char * const imx8mq_pwm1_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_160m", "sys1_pll_40m",
                                         "sys3_pll2_out", "clk_ext1", "sys1_pll_80m", "video_pll1_out", };
 
-static const char *imx8mq_pwm2_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_160m", "sys1_pll_40m",
+static const char * const imx8mq_pwm2_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_160m", "sys1_pll_40m",
                                         "sys3_pll2_out", "clk_ext1", "sys1_pll_80m", "video_pll1_out", };
 
-static const char *imx8mq_pwm3_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_160m", "sys1_pll_40m",
+static const char * const imx8mq_pwm3_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_160m", "sys1_pll_40m",
                                         "sys3_pll2_out", "clk_ext2", "sys1_pll_80m", "video_pll1_out", };
 
-static const char *imx8mq_pwm4_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_160m", "sys1_pll_40m",
+static const char * const imx8mq_pwm4_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_160m", "sys1_pll_40m",
                                         "sys3_pll2_out", "clk_ext2", "sys1_pll_80m", "video_pll1_out", };
 
-static const char *imx8mq_gpt1_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_400m", "sys1_pll_40m",
+static const char * const imx8mq_gpt1_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_400m", "sys1_pll_40m",
                                         "sys1_pll_80m", "audio_pll1_out", "clk_ext1", };
 
-static const char *imx8mq_wdog_sels[] = {"osc_25m", "sys1_pll_133m", "sys1_pll_160m", "vpu_pll_out",
+static const char * const imx8mq_wdog_sels[] = {"osc_25m", "sys1_pll_133m", "sys1_pll_160m", "vpu_pll_out",
                                         "sys2_pll_125m", "sys3_pll2_out", "sys1_pll_80m", "sys2_pll_166m", };
 
-static const char *imx8mq_wrclk_sels[] = {"osc_25m", "sys1_pll_40m", "vpu_pll_out", "sys3_pll2_out", "sys2_pll_200m",
+static const char * const imx8mq_wrclk_sels[] = {"osc_25m", "sys1_pll_40m", "vpu_pll_out", "sys3_pll2_out", "sys2_pll_200m",
                                          "sys1_pll_266m", "sys2_pll_500m", "sys1_pll_100m", };
 
-static const char *imx8mq_dsi_core_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_250m", "sys1_pll_800m",
+static const char * const imx8mq_dsi_core_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_250m", "sys1_pll_800m",
                                             "sys2_pll_1000m", "sys3_pll2_out", "audio_pll2_out", "video_pll1_out", };
 
-static const char *imx8mq_dsi_phy_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_100m", "sys1_pll_800m",
+static const char * const imx8mq_dsi_phy_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_100m", "sys1_pll_800m",
                                            "sys2_pll_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
 
-static const char *imx8mq_dsi_dbi_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_100m", "sys1_pll_800m",
+static const char * const imx8mq_dsi_dbi_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_100m", "sys1_pll_800m",
                                            "sys2_pll_1000m", "sys3_pll2_out", "audio_pll2_out", "video_pll1_out", };
 
-static const char *imx8mq_dsi_esc_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m",
+static const char * const imx8mq_dsi_esc_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m",
                                            "sys2_pll_1000m", "sys3_pll2_out", "clk_ext3", "audio_pll2_out", };
 
-static const char *imx8mq_csi1_core_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_250m", "sys1_pll_800m",
+static const char * const imx8mq_csi1_core_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_250m", "sys1_pll_800m",
                                              "sys2_pll_1000m", "sys3_pll2_out", "audio_pll2_out", "video_pll1_out", };
 
-static const char *imx8mq_csi1_phy_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_100m", "sys1_pll_800m",
+static const char * const imx8mq_csi1_phy_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_100m", "sys1_pll_800m",
                                             "sys2_pll_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
 
-static const char *imx8mq_csi1_esc_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m",
+static const char * const imx8mq_csi1_esc_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m",
                                             "sys2_pll_1000m", "sys3_pll2_out", "clk_ext3", "audio_pll2_out", };
 
-static const char *imx8mq_csi2_core_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_250m", "sys1_pll_800m",
+static const char * const imx8mq_csi2_core_sels[] = {"osc_25m", "sys1_pll_266m", "sys2_pll_250m", "sys1_pll_800m",
                                              "sys2_pll_1000m", "sys3_pll2_out", "audio_pll2_out", "video_pll1_out", };
 
-static const char *imx8mq_csi2_phy_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_100m", "sys1_pll_800m",
+static const char * const imx8mq_csi2_phy_sels[] = {"osc_25m", "sys2_pll_125m", "sys2_pll_100m", "sys1_pll_800m",
                                             "sys2_pll_1000m", "clk_ext2", "audio_pll2_out", "video_pll1_out", };
 
-static const char *imx8mq_csi2_esc_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m",
+static const char * const imx8mq_csi2_esc_sels[] = {"osc_25m", "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_800m",
                                             "sys2_pll_1000m", "sys3_pll2_out", "clk_ext3", "audio_pll2_out", };
 
-static const char *imx8mq_pcie2_ctrl_sels[] = {"osc_25m", "sys2_pll_250m", "sys2_pll_200m", "sys1_pll_266m",
+static const char * const imx8mq_pcie2_ctrl_sels[] = {"osc_25m", "sys2_pll_250m", "sys2_pll_200m", "sys1_pll_266m",
                                               "sys1_pll_800m", "sys2_pll_500m", "sys2_pll_333m", "sys3_pll2_out", };
 
-static const char *imx8mq_pcie2_phy_sels[] = {"osc_25m", "sys2_pll_100m", "sys2_pll_500m", "clk_ext1",
+static const char * const imx8mq_pcie2_phy_sels[] = {"osc_25m", "sys2_pll_100m", "sys2_pll_500m", "clk_ext1",
                                              "clk_ext2", "clk_ext3", "clk_ext4", "sys1_pll_400m", };
 
-static const char *imx8mq_pcie2_aux_sels[] = {"osc_25m", "sys2_pll_200m", "sys2_pll_50m", "sys3_pll2_out",
+static const char * const imx8mq_pcie2_aux_sels[] = {"osc_25m", "sys2_pll_200m", "sys2_pll_50m", "sys3_pll2_out",
                                              "sys2_pll_100m", "sys1_pll_80m", "sys1_pll_160m", "sys1_pll_200m", };
 
-static const char *imx8mq_ecspi3_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_40m", "sys1_pll_160m",
+static const char * const imx8mq_ecspi3_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_40m", "sys1_pll_160m",
                                           "sys1_pll_800m", "sys3_pll2_out", "sys2_pll_250m", "audio_pll2_out", };
-static const char *imx8mq_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
+static const char * const imx8mq_dram_core_sels[] = {"dram_pll_out", "dram_alt_root", };
 
-static const char *imx8mq_clko2_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_400m", "sys2_pll_166m", "audio_pll1_out",
-                                        "video_pll1_out", "ckil", };
+static const char * const imx8mq_clko1_sels[] = {"osc_25m", "sys1_pll_800m", "osc_27m", "sys1_pll_200m",
+                                         "audio_pll2_out", "sys2_pll_500m", "vpu_pll_out", "sys1_pll_80m", };
+static const char * const imx8mq_clko2_sels[] = {"osc_25m", "sys2_pll_200m", "sys1_pll_400m", "sys2_pll_166m",
+                                         "sys3_pll2_out", "audio_pll1_out", "video_pll1_out", "ckil", };
 
 static struct clk_onecell_data clk_data;
 
@@ -308,10 +308,6 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
        clks[IMX8MQ_AUDIO_PLL1_REF_DIV] = imx_clk_divider("audio_pll1_ref_div", "audio_pll1_ref_sel", base + 0x0, 5, 6);
        clks[IMX8MQ_AUDIO_PLL2_REF_DIV] = imx_clk_divider("audio_pll2_ref_div", "audio_pll2_ref_sel", base + 0x8, 5, 6);
        clks[IMX8MQ_VIDEO_PLL1_REF_DIV] = imx_clk_divider("video_pll1_ref_div", "video_pll1_ref_sel", base + 0x10, 5, 6);
-       clks[IMX8MQ_SYS1_PLL1_REF_DIV]  = imx_clk_divider("sys1_pll1_ref_div", "sys1_pll1_ref_sel", base + 0x38, 25, 3);
-       clks[IMX8MQ_SYS2_PLL1_REF_DIV]  = imx_clk_divider("sys2_pll1_ref_div", "sys2_pll1_ref_sel", base + 0x44, 25, 3);
-       clks[IMX8MQ_SYS3_PLL1_REF_DIV]  = imx_clk_divider("sys3_pll1_ref_div", "sys3_pll1_ref_sel", base + 0x50, 25, 3);
-       clks[IMX8MQ_DRAM_PLL1_REF_DIV]  = imx_clk_divider("dram_pll1_ref_div", "dram_pll1_ref_sel", base + 0x68, 25, 3);
 
        clks[IMX8MQ_ARM_PLL] = imx_clk_frac_pll("arm_pll", "arm_pll_ref_div", base + 0x28);
        clks[IMX8MQ_GPU_PLL] = imx_clk_frac_pll("gpu_pll", "gpu_pll_ref_div", base + 0x18);
@@ -319,43 +315,15 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
        clks[IMX8MQ_AUDIO_PLL1] = imx_clk_frac_pll("audio_pll1", "audio_pll1_ref_div", base + 0x0);
        clks[IMX8MQ_AUDIO_PLL2] = imx_clk_frac_pll("audio_pll2", "audio_pll2_ref_div", base + 0x8);
        clks[IMX8MQ_VIDEO_PLL1] = imx_clk_frac_pll("video_pll1", "video_pll1_ref_div", base + 0x10);
-       clks[IMX8MQ_SYS1_PLL1] = imx_clk_sccg_pll("sys1_pll1", "sys1_pll1_ref_div", base + 0x30, SCCG_PLL1);
-       clks[IMX8MQ_SYS2_PLL1] = imx_clk_sccg_pll("sys2_pll1", "sys2_pll1_ref_div", base + 0x3c, SCCG_PLL1);
-       clks[IMX8MQ_SYS3_PLL1] = imx_clk_sccg_pll("sys3_pll1", "sys3_pll1_ref_div", base + 0x48, SCCG_PLL1);
-       clks[IMX8MQ_DRAM_PLL1] = imx_clk_sccg_pll("dram_pll1", "dram_pll1_ref_div", base + 0x60, SCCG_PLL1);
-
-       clks[IMX8MQ_SYS1_PLL2] = imx_clk_sccg_pll("sys1_pll2", "sys1_pll1_out_div", base + 0x30, SCCG_PLL2);
-       clks[IMX8MQ_SYS2_PLL2] = imx_clk_sccg_pll("sys2_pll2", "sys2_pll1_out_div", base + 0x3c, SCCG_PLL2);
-       clks[IMX8MQ_SYS3_PLL2] = imx_clk_sccg_pll("sys3_pll2", "sys3_pll1_out_div", base + 0x48, SCCG_PLL2);
-       clks[IMX8MQ_DRAM_PLL2] = imx_clk_sccg_pll("dram_pll2", "dram_pll1_out_div", base + 0x60, SCCG_PLL2);
-
-       /* PLL divs */
-       clks[IMX8MQ_SYS1_PLL1_OUT_DIV] = imx_clk_divider("sys1_pll1_out_div", "sys1_pll1_out", base + 0x38, 19, 6);
-       clks[IMX8MQ_SYS2_PLL1_OUT_DIV] = imx_clk_divider("sys2_pll1_out_div", "sys2_pll1_out", base + 0x44, 19, 6);
-       clks[IMX8MQ_SYS3_PLL1_OUT_DIV] = imx_clk_divider("sys3_pll1_out_div", "sys3_pll1_out", base + 0x50, 19, 6);
-       clks[IMX8MQ_DRAM_PLL1_OUT_DIV] = imx_clk_divider("dram_pll1_out_div", "dram_pll1_out", base + 0x68, 19, 6);
-       clks[IMX8MQ_SYS1_PLL2_DIV] = imx_clk_divider("sys1_pll2_div", "sys1_pll2", base + 0x38, 1, 6);
-       clks[IMX8MQ_SYS2_PLL2_DIV] = imx_clk_divider("sys2_pll2_div", "sys2_pll2", base + 0x44, 1, 6);
-       clks[IMX8MQ_SYS3_PLL2_DIV] = imx_clk_divider("sys3_pll2_div", "sys3_pll2", base + 0x50, 1, 6);
-       clks[IMX8MQ_DRAM_PLL2_DIV] = imx_clk_divider("dram_pll2_div", "dram_pll2", base + 0x68, 1, 6);
 
        /* PLL bypass out */
-       clks[IMX8MQ_ARM_PLL_BYPASS] = imx_clk_mux("arm_pll_bypass", base + 0x28, 14, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels));
+       clks[IMX8MQ_ARM_PLL_BYPASS] = imx_clk_mux_flags("arm_pll_bypass", base + 0x28, 14, 1, arm_pll_bypass_sels, ARRAY_SIZE(arm_pll_bypass_sels), CLK_SET_RATE_PARENT);
        clks[IMX8MQ_GPU_PLL_BYPASS] = imx_clk_mux("gpu_pll_bypass", base + 0x18, 14, 1, gpu_pll_bypass_sels, ARRAY_SIZE(gpu_pll_bypass_sels));
        clks[IMX8MQ_VPU_PLL_BYPASS] = imx_clk_mux("vpu_pll_bypass", base + 0x20, 14, 1, vpu_pll_bypass_sels, ARRAY_SIZE(vpu_pll_bypass_sels));
        clks[IMX8MQ_AUDIO_PLL1_BYPASS] = imx_clk_mux("audio_pll1_bypass", base + 0x0, 14, 1, audio_pll1_bypass_sels, ARRAY_SIZE(audio_pll1_bypass_sels));
        clks[IMX8MQ_AUDIO_PLL2_BYPASS] = imx_clk_mux("audio_pll2_bypass", base + 0x8, 14, 1, audio_pll2_bypass_sels, ARRAY_SIZE(audio_pll2_bypass_sels));
        clks[IMX8MQ_VIDEO_PLL1_BYPASS] = imx_clk_mux("video_pll1_bypass", base + 0x10, 14, 1, video_pll1_bypass_sels, ARRAY_SIZE(video_pll1_bypass_sels));
 
-       clks[IMX8MQ_SYS1_PLL1_OUT] = imx_clk_mux("sys1_pll1_out", base + 0x30, 5, 1, sys1_pll1_out_sels, ARRAY_SIZE(sys1_pll1_out_sels));
-       clks[IMX8MQ_SYS2_PLL1_OUT] = imx_clk_mux("sys2_pll1_out", base + 0x3c, 5, 1, sys2_pll1_out_sels, ARRAY_SIZE(sys2_pll1_out_sels));
-       clks[IMX8MQ_SYS3_PLL1_OUT] = imx_clk_mux("sys3_pll1_out", base + 0x48, 5, 1, sys3_pll1_out_sels, ARRAY_SIZE(sys3_pll1_out_sels));
-       clks[IMX8MQ_DRAM_PLL1_OUT] = imx_clk_mux("dram_pll1_out", base + 0x60, 5, 1, dram_pll1_out_sels, ARRAY_SIZE(dram_pll1_out_sels));
-       clks[IMX8MQ_SYS1_PLL2_OUT] = imx_clk_mux("sys1_pll2_out", base + 0x30, 4, 1, sys1_pll2_out_sels, ARRAY_SIZE(sys1_pll2_out_sels));
-       clks[IMX8MQ_SYS2_PLL2_OUT] = imx_clk_mux("sys2_pll2_out", base + 0x3c, 4, 1, sys2_pll2_out_sels, ARRAY_SIZE(sys2_pll2_out_sels));
-       clks[IMX8MQ_SYS3_PLL2_OUT] = imx_clk_mux("sys3_pll2_out", base + 0x48, 4, 1, sys3_pll2_out_sels, ARRAY_SIZE(sys3_pll2_out_sels));
-       clks[IMX8MQ_DRAM_PLL2_OUT] = imx_clk_mux("dram_pll2_out", base + 0x60, 4, 1, dram_pll2_out_sels, ARRAY_SIZE(dram_pll2_out_sels));
-
        /* PLL OUT GATE */
        clks[IMX8MQ_ARM_PLL_OUT] = imx_clk_gate("arm_pll_out", "arm_pll_bypass", base + 0x28, 21);
        clks[IMX8MQ_GPU_PLL_OUT] = imx_clk_gate("gpu_pll_out", "gpu_pll_bypass", base + 0x18, 21);
@@ -363,11 +331,11 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
        clks[IMX8MQ_AUDIO_PLL1_OUT] = imx_clk_gate("audio_pll1_out", "audio_pll1_bypass", base + 0x0, 21);
        clks[IMX8MQ_AUDIO_PLL2_OUT] = imx_clk_gate("audio_pll2_out", "audio_pll2_bypass", base + 0x8, 21);
        clks[IMX8MQ_VIDEO_PLL1_OUT] = imx_clk_gate("video_pll1_out", "video_pll1_bypass", base + 0x10, 21);
-       clks[IMX8MQ_SYS1_PLL_OUT] = imx_clk_gate("sys1_pll_out", "sys1_pll2_out", base + 0x30, 9);
-       clks[IMX8MQ_SYS2_PLL_OUT] = imx_clk_gate("sys2_pll_out", "sys2_pll2_out", base + 0x3c, 9);
-       clks[IMX8MQ_SYS3_PLL_OUT] = imx_clk_gate("sys3_pll_out", "sys3_pll2_out", base + 0x48, 9);
-       clks[IMX8MQ_DRAM_PLL_OUT] = imx_clk_gate("dram_pll_out", "dram_pll2_out", base + 0x60, 9);
 
+       clks[IMX8MQ_SYS1_PLL_OUT] = imx_clk_sccg_pll("sys1_pll_out", sys1_pll_out_sels, ARRAY_SIZE(sys1_pll_out_sels), 0, 0, 0, base + 0x30, CLK_IS_CRITICAL);
+       clks[IMX8MQ_SYS2_PLL_OUT] = imx_clk_sccg_pll("sys2_pll_out", sys2_pll_out_sels, ARRAY_SIZE(sys2_pll_out_sels), 0, 0, 1, base + 0x3c, CLK_IS_CRITICAL);
+       clks[IMX8MQ_SYS3_PLL_OUT] = imx_clk_sccg_pll("sys3_pll_out", sys3_pll_out_sels, ARRAY_SIZE(sys3_pll_out_sels), 0, 0, 1, base + 0x48, CLK_IS_CRITICAL);
+       clks[IMX8MQ_DRAM_PLL_OUT] = imx_clk_sccg_pll("dram_pll_out", dram_pll_out_sels, ARRAY_SIZE(dram_pll_out_sels), 0, 0, 0, base + 0x60, CLK_IS_CRITICAL);
        /* SYS PLL fixed output */
        clks[IMX8MQ_SYS1_PLL_40M] = imx_clk_fixed_factor("sys1_pll_40m", "sys1_pll_out", 1, 20);
        clks[IMX8MQ_SYS1_PLL_80M] = imx_clk_fixed_factor("sys1_pll_80m", "sys1_pll_out", 1, 10);
@@ -396,15 +364,19 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
 
        /* CORE */
        clks[IMX8MQ_CLK_A53_SRC] = imx_clk_mux2("arm_a53_src", base + 0x8000, 24, 3, imx8mq_a53_sels, ARRAY_SIZE(imx8mq_a53_sels));
+       clks[IMX8MQ_CLK_M4_SRC] = imx_clk_mux2("arm_m4_src", base + 0x8080, 24, 3, imx8mq_arm_m4_sels, ARRAY_SIZE(imx8mq_arm_m4_sels));
        clks[IMX8MQ_CLK_VPU_SRC] = imx_clk_mux2("vpu_src", base + 0x8100, 24, 3, imx8mq_vpu_sels, ARRAY_SIZE(imx8mq_vpu_sels));
        clks[IMX8MQ_CLK_GPU_CORE_SRC] = imx_clk_mux2("gpu_core_src", base + 0x8180, 24, 3,  imx8mq_gpu_core_sels, ARRAY_SIZE(imx8mq_gpu_core_sels));
        clks[IMX8MQ_CLK_GPU_SHADER_SRC] = imx_clk_mux2("gpu_shader_src", base + 0x8200, 24, 3, imx8mq_gpu_shader_sels,  ARRAY_SIZE(imx8mq_gpu_shader_sels));
+
        clks[IMX8MQ_CLK_A53_CG] = imx_clk_gate3_flags("arm_a53_cg", "arm_a53_src", base + 0x8000, 28, CLK_IS_CRITICAL);
+       clks[IMX8MQ_CLK_M4_CG] = imx_clk_gate3("arm_m4_cg", "arm_m4_src", base + 0x8080, 28);
        clks[IMX8MQ_CLK_VPU_CG] = imx_clk_gate3("vpu_cg", "vpu_src", base + 0x8100, 28);
        clks[IMX8MQ_CLK_GPU_CORE_CG] = imx_clk_gate3("gpu_core_cg", "gpu_core_src", base + 0x8180, 28);
        clks[IMX8MQ_CLK_GPU_SHADER_CG] = imx_clk_gate3("gpu_shader_cg", "gpu_shader_src", base + 0x8200, 28);
 
        clks[IMX8MQ_CLK_A53_DIV] = imx_clk_divider2("arm_a53_div", "arm_a53_cg", base + 0x8000, 0, 3);
+       clks[IMX8MQ_CLK_M4_DIV] = imx_clk_divider2("arm_m4_div", "arm_m4_cg", base + 0x8080, 0, 3);
        clks[IMX8MQ_CLK_VPU_DIV] = imx_clk_divider2("vpu_div", "vpu_cg", base + 0x8100, 0, 3);
        clks[IMX8MQ_CLK_GPU_CORE_DIV] = imx_clk_divider2("gpu_core_div", "gpu_core_cg", base + 0x8180, 0, 3);
        clks[IMX8MQ_CLK_GPU_SHADER_DIV] = imx_clk_divider2("gpu_shader_div", "gpu_shader_cg", base + 0x8200, 0, 3);
@@ -479,6 +451,7 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
        clks[IMX8MQ_CLK_GPT1] = imx8m_clk_composite("gpt1", imx8mq_gpt1_sels, base + 0xb580);
        clks[IMX8MQ_CLK_WDOG] = imx8m_clk_composite("wdog", imx8mq_wdog_sels, base + 0xb900);
        clks[IMX8MQ_CLK_WRCLK] = imx8m_clk_composite("wrclk", imx8mq_wrclk_sels, base + 0xb980);
+       clks[IMX8MQ_CLK_CLKO1] = imx8m_clk_composite("clko1", imx8mq_clko1_sels, base + 0xba00);
        clks[IMX8MQ_CLK_CLKO2] = imx8m_clk_composite("clko2", imx8mq_clko2_sels, base + 0xba80);
        clks[IMX8MQ_CLK_DSI_CORE] = imx8m_clk_composite("dsi_core", imx8mq_dsi_core_sels, base + 0xbb00);
        clks[IMX8MQ_CLK_DSI_PHY_REF] = imx8m_clk_composite("dsi_phy_ref", imx8mq_dsi_phy_sels, base + 0xbb80);
@@ -500,6 +473,11 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
        clks[IMX8MQ_CLK_ECSPI2_ROOT] = imx_clk_gate4("ecspi2_root_clk", "ecspi2", base + 0x4080, 0);
        clks[IMX8MQ_CLK_ECSPI3_ROOT] = imx_clk_gate4("ecspi3_root_clk", "ecspi3", base + 0x4090, 0);
        clks[IMX8MQ_CLK_ENET1_ROOT] = imx_clk_gate4("enet1_root_clk", "enet_axi", base + 0x40a0, 0);
+       clks[IMX8MQ_CLK_GPIO1_ROOT] = imx_clk_gate4("gpio1_root_clk", "ipg_root", base + 0x40b0, 0);
+       clks[IMX8MQ_CLK_GPIO2_ROOT] = imx_clk_gate4("gpio2_root_clk", "ipg_root", base + 0x40c0, 0);
+       clks[IMX8MQ_CLK_GPIO3_ROOT] = imx_clk_gate4("gpio3_root_clk", "ipg_root", base + 0x40d0, 0);
+       clks[IMX8MQ_CLK_GPIO4_ROOT] = imx_clk_gate4("gpio4_root_clk", "ipg_root", base + 0x40e0, 0);
+       clks[IMX8MQ_CLK_GPIO5_ROOT] = imx_clk_gate4("gpio5_root_clk", "ipg_root", base + 0x40f0, 0);
        clks[IMX8MQ_CLK_GPT1_ROOT] = imx_clk_gate4("gpt1_root_clk", "gpt1", base + 0x4100, 0);
        clks[IMX8MQ_CLK_I2C1_ROOT] = imx_clk_gate4("i2c1_root_clk", "i2c1", base + 0x4170, 0);
        clks[IMX8MQ_CLK_I2C2_ROOT] = imx_clk_gate4("i2c2_root_clk", "i2c2", base + 0x4180, 0);
@@ -558,6 +536,12 @@ static int imx8mq_clocks_probe(struct platform_device *pdev)
        clks[IMX8MQ_GPT_3M_CLK] = imx_clk_fixed_factor("gpt_3m", "osc_25m", 1, 8);
        clks[IMX8MQ_CLK_DRAM_ALT_ROOT] = imx_clk_fixed_factor("dram_alt_root", "dram_alt", 1, 4);
 
+       clks[IMX8MQ_CLK_ARM] = imx_clk_cpu("arm", "arm_a53_div",
+                                          clks[IMX8MQ_CLK_A53_DIV],
+                                          clks[IMX8MQ_CLK_A53_SRC],
+                                          clks[IMX8MQ_ARM_PLL_OUT],
+                                          clks[IMX8MQ_SYS1_PLL_800M]);
+
        for (i = 0; i < IMX8MQ_CLK_END; i++)
                if (IS_ERR(clks[i]))
                        pr_err("i.MX8mq clk %u register failed with %ld\n",
index 99c2508..fb6edf1 100644 (file)
@@ -169,6 +169,8 @@ static int imx8qxp_lpcg_clk_probe(struct platform_device *pdev)
                return -ENODEV;
 
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res)
+               return -EINVAL;
        base = devm_ioremap(dev, res->start, resource_size(res));
        if (!base)
                return -ENOMEM;
index 83e2ef9..5e2903e 100644 (file)
@@ -138,6 +138,7 @@ static int imx8qxp_clk_probe(struct platform_device *pdev)
 }
 
 static const struct of_device_id imx8qxp_match[] = {
+       { .compatible = "fsl,scu-clk", },
        { .compatible = "fsl,imx8qxp-clk", },
        { /* sentinel */ }
 };
diff --git a/drivers/clk/imx/clk-pll14xx.c b/drivers/clk/imx/clk-pll14xx.c
new file mode 100644 (file)
index 0000000..1acfa3e
--- /dev/null
@@ -0,0 +1,392 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright 2017-2018 NXP.
+ */
+
+#include <linux/bitops.h>
+#include <linux/clk-provider.h>
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/iopoll.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+
+#include "clk.h"
+
+#define GNRL_CTL       0x0
+#define DIV_CTL                0x4
+#define LOCK_STATUS    BIT(31)
+#define LOCK_SEL_MASK  BIT(29)
+#define CLKE_MASK      BIT(11)
+#define RST_MASK       BIT(9)
+#define BYPASS_MASK    BIT(4)
+#define MDIV_SHIFT     12
+#define MDIV_MASK      GENMASK(21, 12)
+#define PDIV_SHIFT     4
+#define PDIV_MASK      GENMASK(9, 4)
+#define SDIV_SHIFT     0
+#define SDIV_MASK      GENMASK(2, 0)
+#define KDIV_SHIFT     0
+#define KDIV_MASK      GENMASK(15, 0)
+
+#define LOCK_TIMEOUT_US                10000
+
+struct clk_pll14xx {
+       struct clk_hw                   hw;
+       void __iomem                    *base;
+       enum imx_pll14xx_type           type;
+       const struct imx_pll14xx_rate_table *rate_table;
+       int rate_count;
+};
+
+#define to_clk_pll14xx(_hw) container_of(_hw, struct clk_pll14xx, hw)
+
+static const struct imx_pll14xx_rate_table *imx_get_pll_settings(
+               struct clk_pll14xx *pll, unsigned long rate)
+{
+       const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
+       int i;
+
+       for (i = 0; i < pll->rate_count; i++)
+               if (rate == rate_table[i].rate)
+                       return &rate_table[i];
+
+       return NULL;
+}
+
+static long clk_pll14xx_round_rate(struct clk_hw *hw, unsigned long rate,
+                       unsigned long *prate)
+{
+       struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+       const struct imx_pll14xx_rate_table *rate_table = pll->rate_table;
+       int i;
+
+       /* Assumming rate_table is in descending order */
+       for (i = 0; i < pll->rate_count; i++)
+               if (rate >= rate_table[i].rate)
+                       return rate_table[i].rate;
+
+       /* return minimum supported value */
+       return rate_table[i - 1].rate;
+}
+
+static unsigned long clk_pll1416x_recalc_rate(struct clk_hw *hw,
+                                                 unsigned long parent_rate)
+{
+       struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+       u32 mdiv, pdiv, sdiv, pll_gnrl, pll_div;
+       u64 fvco = parent_rate;
+
+       pll_gnrl = readl_relaxed(pll->base);
+       pll_div = readl_relaxed(pll->base + 4);
+       mdiv = (pll_div & MDIV_MASK) >> MDIV_SHIFT;
+       pdiv = (pll_div & PDIV_MASK) >> PDIV_SHIFT;
+       sdiv = (pll_div & SDIV_MASK) >> SDIV_SHIFT;
+
+       fvco *= mdiv;
+       do_div(fvco, pdiv << sdiv);
+
+       return fvco;
+}
+
+static unsigned long clk_pll1443x_recalc_rate(struct clk_hw *hw,
+                                                 unsigned long parent_rate)
+{
+       struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+       u32 mdiv, pdiv, sdiv, pll_gnrl, pll_div_ctl0, pll_div_ctl1;
+       short int kdiv;
+       u64 fvco = parent_rate;
+
+       pll_gnrl = readl_relaxed(pll->base);
+       pll_div_ctl0 = readl_relaxed(pll->base + 4);
+       pll_div_ctl1 = readl_relaxed(pll->base + 8);
+       mdiv = (pll_div_ctl0 & MDIV_MASK) >> MDIV_SHIFT;
+       pdiv = (pll_div_ctl0 & PDIV_MASK) >> PDIV_SHIFT;
+       sdiv = (pll_div_ctl0 & SDIV_MASK) >> SDIV_SHIFT;
+       kdiv = pll_div_ctl1 & KDIV_MASK;
+
+       /* fvco = (m * 65536 + k) * Fin / (p * 65536) */
+       fvco *= (mdiv * 65536 + kdiv);
+       pdiv *= 65536;
+
+       do_div(fvco, pdiv << sdiv);
+
+       return fvco;
+}
+
+static inline bool clk_pll1416x_mp_change(const struct imx_pll14xx_rate_table *rate,
+                                         u32 pll_div)
+{
+       u32 old_mdiv, old_pdiv;
+
+       old_mdiv = (pll_div >> MDIV_SHIFT) & MDIV_MASK;
+       old_pdiv = (pll_div >> PDIV_SHIFT) & PDIV_MASK;
+
+       return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv;
+}
+
+static inline bool clk_pll1443x_mpk_change(const struct imx_pll14xx_rate_table *rate,
+                                         u32 pll_div_ctl0, u32 pll_div_ctl1)
+{
+       u32 old_mdiv, old_pdiv, old_kdiv;
+
+       old_mdiv = (pll_div_ctl0 >> MDIV_SHIFT) & MDIV_MASK;
+       old_pdiv = (pll_div_ctl0 >> PDIV_SHIFT) & PDIV_MASK;
+       old_kdiv = (pll_div_ctl1 >> KDIV_SHIFT) & KDIV_MASK;
+
+       return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
+               rate->kdiv != old_kdiv;
+}
+
+static inline bool clk_pll1443x_mp_change(const struct imx_pll14xx_rate_table *rate,
+                                         u32 pll_div_ctl0, u32 pll_div_ctl1)
+{
+       u32 old_mdiv, old_pdiv, old_kdiv;
+
+       old_mdiv = (pll_div_ctl0 >> MDIV_SHIFT) & MDIV_MASK;
+       old_pdiv = (pll_div_ctl0 >> PDIV_SHIFT) & PDIV_MASK;
+       old_kdiv = (pll_div_ctl1 >> KDIV_SHIFT) & KDIV_MASK;
+
+       return rate->mdiv != old_mdiv || rate->pdiv != old_pdiv ||
+               rate->kdiv != old_kdiv;
+}
+
+static int clk_pll14xx_wait_lock(struct clk_pll14xx *pll)
+{
+       u32 val;
+
+       return readl_poll_timeout(pll->base, val, val & LOCK_TIMEOUT_US, 0,
+                       LOCK_TIMEOUT_US);
+}
+
+static int clk_pll1416x_set_rate(struct clk_hw *hw, unsigned long drate,
+                                unsigned long prate)
+{
+       struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+       const struct imx_pll14xx_rate_table *rate;
+       u32 tmp, div_val;
+       int ret;
+
+       rate = imx_get_pll_settings(pll, drate);
+       if (!rate) {
+               pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+                      drate, clk_hw_get_name(hw));
+               return -EINVAL;
+       }
+
+       tmp = readl_relaxed(pll->base + 4);
+
+       if (!clk_pll1416x_mp_change(rate, tmp)) {
+               tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
+               tmp |= rate->sdiv << SDIV_SHIFT;
+               writel_relaxed(tmp, pll->base + 4);
+
+               return 0;
+       }
+
+       /* Bypass clock and set lock to pll output lock */
+       tmp = readl_relaxed(pll->base);
+       tmp |= LOCK_SEL_MASK;
+       writel_relaxed(tmp, pll->base);
+
+       /* Enable RST */
+       tmp &= ~RST_MASK;
+       writel_relaxed(tmp, pll->base);
+
+       div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
+               (rate->sdiv << SDIV_SHIFT);
+       writel_relaxed(div_val, pll->base + 0x4);
+
+       /*
+        * According to SPEC, t3 - t2 need to be greater than
+        * 1us and 1/FREF, respectively.
+        * FREF is FIN / Prediv, the prediv is [1, 63], so choose
+        * 3us.
+        */
+       udelay(3);
+
+       /* Disable RST */
+       tmp |= RST_MASK;
+       writel_relaxed(tmp, pll->base);
+
+       /* Wait Lock */
+       ret = clk_pll14xx_wait_lock(pll);
+       if (ret)
+               return ret;
+
+       /* Bypass */
+       tmp &= ~BYPASS_MASK;
+       writel_relaxed(tmp, pll->base);
+
+       return 0;
+}
+
+static int clk_pll1443x_set_rate(struct clk_hw *hw, unsigned long drate,
+                                unsigned long prate)
+{
+       struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+       const struct imx_pll14xx_rate_table *rate;
+       u32 tmp, div_val;
+       int ret;
+
+       rate = imx_get_pll_settings(pll, drate);
+       if (!rate) {
+               pr_err("%s: Invalid rate : %lu for pll clk %s\n", __func__,
+                       drate, clk_hw_get_name(hw));
+               return -EINVAL;
+       }
+
+       tmp = readl_relaxed(pll->base + 4);
+       div_val = readl_relaxed(pll->base + 8);
+
+       if (!clk_pll1443x_mpk_change(rate, tmp, div_val)) {
+               tmp &= ~(SDIV_MASK) << SDIV_SHIFT;
+               tmp |= rate->sdiv << SDIV_SHIFT;
+               writel_relaxed(tmp, pll->base + 4);
+
+               return 0;
+       }
+
+       /* Enable RST */
+       tmp = readl_relaxed(pll->base);
+       tmp &= ~RST_MASK;
+       writel_relaxed(tmp, pll->base);
+
+       div_val = (rate->mdiv << MDIV_SHIFT) | (rate->pdiv << PDIV_SHIFT) |
+               (rate->sdiv << SDIV_SHIFT);
+       writel_relaxed(div_val, pll->base + 0x4);
+       writel_relaxed(rate->kdiv << KDIV_SHIFT, pll->base + 0x8);
+
+       /*
+        * According to SPEC, t3 - t2 need to be greater than
+        * 1us and 1/FREF, respectively.
+        * FREF is FIN / Prediv, the prediv is [1, 63], so choose
+        * 3us.
+        */
+       udelay(3);
+
+       /* Disable RST */
+       tmp |= RST_MASK;
+       writel_relaxed(tmp, pll->base);
+
+       /* Wait Lock*/
+       ret = clk_pll14xx_wait_lock(pll);
+       if (ret)
+               return ret;
+
+       /* Bypass */
+       tmp &= ~BYPASS_MASK;
+       writel_relaxed(tmp, pll->base);
+
+       return 0;
+}
+
+static int clk_pll14xx_prepare(struct clk_hw *hw)
+{
+       struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+       u32 val;
+
+       /*
+        * RESETB = 1 from 0, PLL starts its normal
+        * operation after lock time
+        */
+       val = readl_relaxed(pll->base + GNRL_CTL);
+       val |= RST_MASK;
+       writel_relaxed(val, pll->base + GNRL_CTL);
+
+       return clk_pll14xx_wait_lock(pll);
+}
+
+static int clk_pll14xx_is_prepared(struct clk_hw *hw)
+{
+       struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+       u32 val;
+
+       val = readl_relaxed(pll->base + GNRL_CTL);
+
+       return (val & RST_MASK) ? 1 : 0;
+}
+
+static void clk_pll14xx_unprepare(struct clk_hw *hw)
+{
+       struct clk_pll14xx *pll = to_clk_pll14xx(hw);
+       u32 val;
+
+       /*
+        * Set RST to 0, power down mode is enabled and
+        * every digital block is reset
+        */
+       val = readl_relaxed(pll->base + GNRL_CTL);
+       val &= ~RST_MASK;
+       writel_relaxed(val, pll->base + GNRL_CTL);
+}
+
+static const struct clk_ops clk_pll1416x_ops = {
+       .prepare        = clk_pll14xx_prepare,
+       .unprepare      = clk_pll14xx_unprepare,
+       .is_prepared    = clk_pll14xx_is_prepared,
+       .recalc_rate    = clk_pll1416x_recalc_rate,
+       .round_rate     = clk_pll14xx_round_rate,
+       .set_rate       = clk_pll1416x_set_rate,
+};
+
+static const struct clk_ops clk_pll1416x_min_ops = {
+       .recalc_rate    = clk_pll1416x_recalc_rate,
+};
+
+static const struct clk_ops clk_pll1443x_ops = {
+       .prepare        = clk_pll14xx_prepare,
+       .unprepare      = clk_pll14xx_unprepare,
+       .is_prepared    = clk_pll14xx_is_prepared,
+       .recalc_rate    = clk_pll1443x_recalc_rate,
+       .round_rate     = clk_pll14xx_round_rate,
+       .set_rate       = clk_pll1443x_set_rate,
+};
+
+struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
+                           void __iomem *base,
+                           const struct imx_pll14xx_clk *pll_clk)
+{
+       struct clk_pll14xx *pll;
+       struct clk *clk;
+       struct clk_init_data init;
+
+       pll = kzalloc(sizeof(*pll), GFP_KERNEL);
+       if (!pll)
+               return ERR_PTR(-ENOMEM);
+
+       init.name = name;
+       init.flags = pll_clk->flags;
+       init.parent_names = &parent_name;
+       init.num_parents = 1;
+
+       switch (pll_clk->type) {
+       case PLL_1416X:
+               if (!pll->rate_table)
+                       init.ops = &clk_pll1416x_min_ops;
+               else
+                       init.ops = &clk_pll1416x_ops;
+               break;
+       case PLL_1443X:
+               init.ops = &clk_pll1443x_ops;
+               break;
+       default:
+               pr_err("%s: Unknown pll type for pll clk %s\n",
+                      __func__, name);
+       };
+
+       pll->base = base;
+       pll->hw.init = &init;
+       pll->type = pll_clk->type;
+       pll->rate_table = pll_clk->rate_table;
+       pll->rate_count = pll_clk->rate_count;
+
+       clk = clk_register(NULL, &pll->hw);
+       if (IS_ERR(clk)) {
+               pr_err("%s: failed to register pll %s %lu\n",
+                       __func__, name, PTR_ERR(clk));
+               kfree(pll);
+       }
+
+       return clk;
+}
index ee7752b..9dfd03a 100644 (file)
 #define PLL_DIVF2_MASK         GENMASK(12, 7)
 #define PLL_DIVR1_MASK         GENMASK(27, 25)
 #define PLL_DIVR2_MASK         GENMASK(24, 19)
+#define PLL_DIVQ_MASK           GENMASK(6, 1)
 #define PLL_REF_MASK           GENMASK(2, 0)
 
 #define PLL_LOCK_MASK          BIT(31)
 #define PLL_PD_MASK            BIT(7)
 
-#define OSC_25M                        25000000
-#define OSC_27M                        27000000
+/* These are the specification limits for the SSCG PLL */
+#define PLL_REF_MIN_FREQ               25000000UL
+#define PLL_REF_MAX_FREQ               235000000UL
 
-#define PLL_SCCG_LOCK_TIMEOUT  70
+#define PLL_STAGE1_MIN_FREQ            1600000000UL
+#define PLL_STAGE1_MAX_FREQ            2400000000UL
+
+#define PLL_STAGE1_REF_MIN_FREQ                25000000UL
+#define PLL_STAGE1_REF_MAX_FREQ                54000000UL
+
+#define PLL_STAGE2_MIN_FREQ            1200000000UL
+#define PLL_STAGE2_MAX_FREQ            2400000000UL
+
+#define PLL_STAGE2_REF_MIN_FREQ                54000000UL
+#define PLL_STAGE2_REF_MAX_FREQ                75000000UL
+
+#define PLL_OUT_MIN_FREQ               20000000UL
+#define PLL_OUT_MAX_FREQ               1200000000UL
+
+#define PLL_DIVR1_MAX                  7
+#define PLL_DIVR2_MAX                  63
+#define PLL_DIVF1_MAX                  63
+#define PLL_DIVF2_MAX                  63
+#define PLL_DIVQ_MAX                   63
+
+#define PLL_BYPASS_NONE                        0x0
+#define PLL_BYPASS1                    0x2
+#define PLL_BYPASS2                    0x1
+
+#define SSCG_PLL_BYPASS1_MASK           BIT(5)
+#define SSCG_PLL_BYPASS2_MASK           BIT(4)
+#define SSCG_PLL_BYPASS_MASK           GENMASK(5, 4)
+
+#define PLL_SCCG_LOCK_TIMEOUT          70
+
+struct clk_sccg_pll_setup {
+       int divr1, divf1;
+       int divr2, divf2;
+       int divq;
+       int bypass;
+
+       uint64_t vco1;
+       uint64_t vco2;
+       uint64_t fout;
+       uint64_t ref;
+       uint64_t ref_div1;
+       uint64_t ref_div2;
+       uint64_t fout_request;
+       int fout_error;
+};
 
 struct clk_sccg_pll {
        struct clk_hw   hw;
-       void __iomem    *base;
+       const struct clk_ops  ops;
+
+       void __iomem *base;
+
+       struct clk_sccg_pll_setup setup;
+
+       u8 parent;
+       u8 bypass1;
+       u8 bypass2;
 };
 
 #define to_clk_sccg_pll(_hw) container_of(_hw, struct clk_sccg_pll, hw)
 
-static int clk_pll_wait_lock(struct clk_sccg_pll *pll)
+static int clk_sccg_pll_wait_lock(struct clk_sccg_pll *pll)
 {
        u32 val;
 
-       return readl_poll_timeout(pll->base, val, val & PLL_LOCK_MASK, 0,
-                                       PLL_SCCG_LOCK_TIMEOUT);
+       val = readl_relaxed(pll->base + PLL_CFG0);
+
+       /* don't wait for lock if all plls are bypassed */
+       if (!(val & SSCG_PLL_BYPASS2_MASK))
+               return readl_poll_timeout(pll->base, val, val & PLL_LOCK_MASK,
+                                               0, PLL_SCCG_LOCK_TIMEOUT);
+
+       return 0;
 }
 
-static int clk_pll1_is_prepared(struct clk_hw *hw)
+static int clk_sccg_pll2_check_match(struct clk_sccg_pll_setup *setup,
+                                       struct clk_sccg_pll_setup *temp_setup)
 {
-       struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
-       u32 val;
+       int new_diff = temp_setup->fout - temp_setup->fout_request;
+       int diff = temp_setup->fout_error;
 
-       val = readl_relaxed(pll->base + PLL_CFG0);
-       return (val & PLL_PD_MASK) ? 0 : 1;
+       if (abs(diff) > abs(new_diff)) {
+               temp_setup->fout_error = new_diff;
+               memcpy(setup, temp_setup, sizeof(struct clk_sccg_pll_setup));
+
+               if (temp_setup->fout_request == temp_setup->fout)
+                       return 0;
+       }
+       return -1;
 }
 
-static unsigned long clk_pll1_recalc_rate(struct clk_hw *hw,
-                                        unsigned long parent_rate)
+static int clk_sccg_divq_lookup(struct clk_sccg_pll_setup *setup,
+                               struct clk_sccg_pll_setup *temp_setup)
 {
-       struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
-       u32 val, divf;
+       int ret = -EINVAL;
+
+       for (temp_setup->divq = 0; temp_setup->divq <= PLL_DIVQ_MAX;
+            temp_setup->divq++) {
+               temp_setup->vco2 = temp_setup->vco1;
+               do_div(temp_setup->vco2, temp_setup->divr2 + 1);
+               temp_setup->vco2 *= 2;
+               temp_setup->vco2 *= temp_setup->divf2 + 1;
+               if (temp_setup->vco2 >= PLL_STAGE2_MIN_FREQ &&
+                               temp_setup->vco2 <= PLL_STAGE2_MAX_FREQ) {
+                       temp_setup->fout = temp_setup->vco2;
+                       do_div(temp_setup->fout, 2 * (temp_setup->divq + 1));
+
+                       ret = clk_sccg_pll2_check_match(setup, temp_setup);
+                       if (!ret) {
+                               temp_setup->bypass = PLL_BYPASS1;
+                               return ret;
+                       }
+               }
+       }
 
-       val = readl_relaxed(pll->base + PLL_CFG2);
-       divf = FIELD_GET(PLL_DIVF1_MASK, val);
+       return ret;
+}
+
+static int clk_sccg_divf2_lookup(struct clk_sccg_pll_setup *setup,
+                                       struct clk_sccg_pll_setup *temp_setup)
+{
+       int ret = -EINVAL;
+
+       for (temp_setup->divf2 = 0; temp_setup->divf2 <= PLL_DIVF2_MAX;
+            temp_setup->divf2++) {
+               ret = clk_sccg_divq_lookup(setup, temp_setup);
+               if (!ret)
+                       return ret;
+       }
 
-       return parent_rate * 2 * (divf + 1);
+       return ret;
 }
 
-static long clk_pll1_round_rate(struct clk_hw *hw, unsigned long rate,
-                              unsigned long *prate)
+static int clk_sccg_divr2_lookup(struct clk_sccg_pll_setup *setup,
+                               struct clk_sccg_pll_setup *temp_setup)
 {
-       unsigned long parent_rate = *prate;
-       u32 div;
+       int ret = -EINVAL;
+
+       for (temp_setup->divr2 = 0; temp_setup->divr2 <= PLL_DIVR2_MAX;
+            temp_setup->divr2++) {
+               temp_setup->ref_div2 = temp_setup->vco1;
+               do_div(temp_setup->ref_div2, temp_setup->divr2 + 1);
+               if (temp_setup->ref_div2 >= PLL_STAGE2_REF_MIN_FREQ &&
+                   temp_setup->ref_div2 <= PLL_STAGE2_REF_MAX_FREQ) {
+                       ret = clk_sccg_divf2_lookup(setup, temp_setup);
+                       if (!ret)
+                               return ret;
+               }
+       }
+
+       return ret;
+}
+
+static int clk_sccg_pll2_find_setup(struct clk_sccg_pll_setup *setup,
+                                       struct clk_sccg_pll_setup *temp_setup,
+                                       uint64_t ref)
+{
+
+       int ret = -EINVAL;
 
-       if (!parent_rate)
-               return 0;
+       if (ref < PLL_STAGE1_MIN_FREQ || ref > PLL_STAGE1_MAX_FREQ)
+               return ret;
 
-       div = rate / (parent_rate * 2);
+       temp_setup->vco1 = ref;
 
-       return parent_rate * div * 2;
+       ret = clk_sccg_divr2_lookup(setup, temp_setup);
+       return ret;
 }
 
-static int clk_pll1_set_rate(struct clk_hw *hw, unsigned long rate,
-                           unsigned long parent_rate)
+static int clk_sccg_divf1_lookup(struct clk_sccg_pll_setup *setup,
+                               struct clk_sccg_pll_setup *temp_setup)
 {
-       struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
-       u32 val;
-       u32 divf;
+       int ret = -EINVAL;
 
-       if (!parent_rate)
-               return -EINVAL;
+       for (temp_setup->divf1 = 0; temp_setup->divf1 <= PLL_DIVF1_MAX;
+            temp_setup->divf1++) {
+               uint64_t vco1 = temp_setup->ref;
 
-       divf = rate / (parent_rate * 2);
+               do_div(vco1, temp_setup->divr1 + 1);
+               vco1 *= 2;
+               vco1 *= temp_setup->divf1 + 1;
 
-       val = readl_relaxed(pll->base + PLL_CFG2);
-       val &= ~PLL_DIVF1_MASK;
-       val |= FIELD_PREP(PLL_DIVF1_MASK, divf - 1);
-       writel_relaxed(val, pll->base + PLL_CFG2);
+               ret = clk_sccg_pll2_find_setup(setup, temp_setup, vco1);
+               if (!ret) {
+                       temp_setup->bypass = PLL_BYPASS_NONE;
+                       return ret;
+               }
+       }
+
+       return ret;
+}
+
+static int clk_sccg_divr1_lookup(struct clk_sccg_pll_setup *setup,
+                               struct clk_sccg_pll_setup *temp_setup)
+{
+       int ret = -EINVAL;
+
+       for (temp_setup->divr1 = 0; temp_setup->divr1 <= PLL_DIVR1_MAX;
+            temp_setup->divr1++) {
+               temp_setup->ref_div1 = temp_setup->ref;
+               do_div(temp_setup->ref_div1, temp_setup->divr1 + 1);
+               if (temp_setup->ref_div1 >= PLL_STAGE1_REF_MIN_FREQ &&
+                   temp_setup->ref_div1 <= PLL_STAGE1_REF_MAX_FREQ) {
+                       ret = clk_sccg_divf1_lookup(setup, temp_setup);
+                       if (!ret)
+                               return ret;
+               }
+       }
+
+       return ret;
+}
+
+static int clk_sccg_pll1_find_setup(struct clk_sccg_pll_setup *setup,
+                                       struct clk_sccg_pll_setup *temp_setup,
+                                       uint64_t ref)
+{
+
+       int ret = -EINVAL;
+
+       if (ref < PLL_REF_MIN_FREQ || ref > PLL_REF_MAX_FREQ)
+               return ret;
+
+       temp_setup->ref = ref;
+
+       ret = clk_sccg_divr1_lookup(setup, temp_setup);
+
+       return ret;
+}
+
+static int clk_sccg_pll_find_setup(struct clk_sccg_pll_setup *setup,
+                                       uint64_t prate,
+                                       uint64_t rate, int try_bypass)
+{
+       struct clk_sccg_pll_setup temp_setup;
+       int ret = -EINVAL;
+
+       memset(&temp_setup, 0, sizeof(struct clk_sccg_pll_setup));
+       memset(setup, 0, sizeof(struct clk_sccg_pll_setup));
+
+       temp_setup.fout_error = PLL_OUT_MAX_FREQ;
+       temp_setup.fout_request = rate;
+
+       switch (try_bypass) {
 
-       return clk_pll_wait_lock(pll);
+       case PLL_BYPASS2:
+               if (prate == rate) {
+                       setup->bypass = PLL_BYPASS2;
+                       setup->fout = rate;
+                       ret = 0;
+               }
+               break;
+
+       case PLL_BYPASS1:
+               ret = clk_sccg_pll2_find_setup(setup, &temp_setup, prate);
+               break;
+
+       case PLL_BYPASS_NONE:
+               ret = clk_sccg_pll1_find_setup(setup, &temp_setup, prate);
+               break;
+       }
+
+       return ret;
+}
+
+
+static int clk_sccg_pll_is_prepared(struct clk_hw *hw)
+{
+       struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+
+       u32 val = readl_relaxed(pll->base + PLL_CFG0);
+
+       return (val & PLL_PD_MASK) ? 0 : 1;
 }
 
-static int clk_pll1_prepare(struct clk_hw *hw)
+static int clk_sccg_pll_prepare(struct clk_hw *hw)
 {
        struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
        u32 val;
@@ -114,10 +319,10 @@ static int clk_pll1_prepare(struct clk_hw *hw)
        val &= ~PLL_PD_MASK;
        writel_relaxed(val, pll->base + PLL_CFG0);
 
-       return clk_pll_wait_lock(pll);
+       return clk_sccg_pll_wait_lock(pll);
 }
 
-static void clk_pll1_unprepare(struct clk_hw *hw)
+static void clk_sccg_pll_unprepare(struct clk_hw *hw)
 {
        struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
        u32 val;
@@ -125,121 +330,208 @@ static void clk_pll1_unprepare(struct clk_hw *hw)
        val = readl_relaxed(pll->base + PLL_CFG0);
        val |= PLL_PD_MASK;
        writel_relaxed(val, pll->base + PLL_CFG0);
-
 }
 
-static unsigned long clk_pll2_recalc_rate(struct clk_hw *hw,
+static unsigned long clk_sccg_pll_recalc_rate(struct clk_hw *hw,
                                         unsigned long parent_rate)
 {
        struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
-       u32 val, ref, divr1, divf1, divr2, divf2;
+       u32 val, divr1, divf1, divr2, divf2, divq;
        u64 temp64;
 
-       val = readl_relaxed(pll->base + PLL_CFG0);
-       switch (FIELD_GET(PLL_REF_MASK, val)) {
-       case 0:
-               ref = OSC_25M;
-               break;
-       case 1:
-               ref = OSC_27M;
-               break;
-       default:
-               ref = OSC_25M;
-               break;
-       }
-
        val = readl_relaxed(pll->base + PLL_CFG2);
        divr1 = FIELD_GET(PLL_DIVR1_MASK, val);
        divr2 = FIELD_GET(PLL_DIVR2_MASK, val);
        divf1 = FIELD_GET(PLL_DIVF1_MASK, val);
        divf2 = FIELD_GET(PLL_DIVF2_MASK, val);
-
-       temp64 = ref * 2;
-       temp64 *= (divf1 + 1) * (divf2 + 1);
-
-       do_div(temp64, (divr1 + 1) * (divr2 + 1));
+       divq = FIELD_GET(PLL_DIVQ_MASK, val);
+
+       temp64 = parent_rate;
+
+       val = clk_readl(pll->base + PLL_CFG0);
+       if (val & SSCG_PLL_BYPASS2_MASK) {
+               temp64 = parent_rate;
+       } else if (val & SSCG_PLL_BYPASS1_MASK) {
+               temp64 *= divf2;
+               do_div(temp64, (divr2 + 1) * (divq + 1));
+       } else {
+               temp64 *= 2;
+               temp64 *= (divf1 + 1) * (divf2 + 1);
+               do_div(temp64, (divr1 + 1) * (divr2 + 1) * (divq + 1));
+       }
 
        return temp64;
 }
 
-static long clk_pll2_round_rate(struct clk_hw *hw, unsigned long rate,
-                              unsigned long *prate)
+static int clk_sccg_pll_set_rate(struct clk_hw *hw, unsigned long rate,
+                           unsigned long parent_rate)
 {
-       u32 div;
-       unsigned long parent_rate = *prate;
+       struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+       struct clk_sccg_pll_setup *setup = &pll->setup;
+       u32 val;
 
-       if (!parent_rate)
-               return 0;
+       /* set bypass here too since the parent might be the same */
+       val = clk_readl(pll->base + PLL_CFG0);
+       val &= ~SSCG_PLL_BYPASS_MASK;
+       val |= FIELD_PREP(SSCG_PLL_BYPASS_MASK, setup->bypass);
+       clk_writel(val, pll->base + PLL_CFG0);
 
-       div = rate / parent_rate;
+       val = readl_relaxed(pll->base + PLL_CFG2);
+       val &= ~(PLL_DIVF1_MASK | PLL_DIVF2_MASK);
+       val &= ~(PLL_DIVR1_MASK | PLL_DIVR2_MASK | PLL_DIVQ_MASK);
+       val |= FIELD_PREP(PLL_DIVF1_MASK, setup->divf1);
+       val |= FIELD_PREP(PLL_DIVF2_MASK, setup->divf2);
+       val |= FIELD_PREP(PLL_DIVR1_MASK, setup->divr1);
+       val |= FIELD_PREP(PLL_DIVR2_MASK, setup->divr2);
+       val |= FIELD_PREP(PLL_DIVQ_MASK, setup->divq);
+       writel_relaxed(val, pll->base + PLL_CFG2);
 
-       return parent_rate * div;
+       return clk_sccg_pll_wait_lock(pll);
 }
 
-static int clk_pll2_set_rate(struct clk_hw *hw, unsigned long rate,
-                           unsigned long parent_rate)
+static u8 clk_sccg_pll_get_parent(struct clk_hw *hw)
 {
+       struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
        u32 val;
-       u32 divf;
+       u8 ret = pll->parent;
+
+       val = clk_readl(pll->base + PLL_CFG0);
+       if (val & SSCG_PLL_BYPASS2_MASK)
+               ret = pll->bypass2;
+       else if (val & SSCG_PLL_BYPASS1_MASK)
+               ret = pll->bypass1;
+       return ret;
+}
+
+static int clk_sccg_pll_set_parent(struct clk_hw *hw, u8 index)
+{
        struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+       u32 val;
 
-       if (!parent_rate)
-               return -EINVAL;
+       val = clk_readl(pll->base + PLL_CFG0);
+       val &= ~SSCG_PLL_BYPASS_MASK;
+       val |= FIELD_PREP(SSCG_PLL_BYPASS_MASK, pll->setup.bypass);
+       clk_writel(val, pll->base + PLL_CFG0);
 
-       divf = rate / parent_rate;
+       return clk_sccg_pll_wait_lock(pll);
+}
 
-       val = readl_relaxed(pll->base + PLL_CFG2);
-       val &= ~PLL_DIVF2_MASK;
-       val |= FIELD_PREP(PLL_DIVF2_MASK, divf - 1);
-       writel_relaxed(val, pll->base + PLL_CFG2);
+static int __clk_sccg_pll_determine_rate(struct clk_hw *hw,
+                                       struct clk_rate_request *req,
+                                       uint64_t min,
+                                       uint64_t max,
+                                       uint64_t rate,
+                                       int bypass)
+{
+       struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+       struct clk_sccg_pll_setup *setup = &pll->setup;
+       struct clk_hw *parent_hw = NULL;
+       int bypass_parent_index;
+       int ret = -EINVAL;
+
+       req->max_rate = max;
+       req->min_rate = min;
+
+       switch (bypass) {
+       case PLL_BYPASS2:
+               bypass_parent_index = pll->bypass2;
+               break;
+       case PLL_BYPASS1:
+               bypass_parent_index = pll->bypass1;
+               break;
+       default:
+               bypass_parent_index = pll->parent;
+               break;
+       }
+
+       parent_hw = clk_hw_get_parent_by_index(hw, bypass_parent_index);
+       ret = __clk_determine_rate(parent_hw, req);
+       if (!ret) {
+               ret = clk_sccg_pll_find_setup(setup, req->rate,
+                                               rate, bypass);
+       }
+
+       req->best_parent_hw = parent_hw;
+       req->best_parent_rate = req->rate;
+       req->rate = setup->fout;
 
-       return clk_pll_wait_lock(pll);
+       return ret;
 }
 
-static const struct clk_ops clk_sccg_pll1_ops = {
-       .is_prepared    = clk_pll1_is_prepared,
-       .recalc_rate    = clk_pll1_recalc_rate,
-       .round_rate     = clk_pll1_round_rate,
-       .set_rate       = clk_pll1_set_rate,
-};
+static int clk_sccg_pll_determine_rate(struct clk_hw *hw,
+                                      struct clk_rate_request *req)
+{
+       struct clk_sccg_pll *pll = to_clk_sccg_pll(hw);
+       struct clk_sccg_pll_setup *setup = &pll->setup;
+       uint64_t rate = req->rate;
+       uint64_t min = req->min_rate;
+       uint64_t max = req->max_rate;
+       int ret = -EINVAL;
+
+       if (rate < PLL_OUT_MIN_FREQ || rate > PLL_OUT_MAX_FREQ)
+               return ret;
+
+       ret = __clk_sccg_pll_determine_rate(hw, req, req->rate, req->rate,
+                                               rate, PLL_BYPASS2);
+       if (!ret)
+               return ret;
+
+       ret = __clk_sccg_pll_determine_rate(hw, req, PLL_STAGE1_REF_MIN_FREQ,
+                                               PLL_STAGE1_REF_MAX_FREQ, rate,
+                                               PLL_BYPASS1);
+       if (!ret)
+               return ret;
+
+       ret = __clk_sccg_pll_determine_rate(hw, req, PLL_REF_MIN_FREQ,
+                                               PLL_REF_MAX_FREQ, rate,
+                                               PLL_BYPASS_NONE);
+       if (!ret)
+               return ret;
+
+       if (setup->fout >= min && setup->fout <= max)
+               ret = 0;
+
+       return ret;
+}
 
-static const struct clk_ops clk_sccg_pll2_ops = {
-       .prepare        = clk_pll1_prepare,
-       .unprepare      = clk_pll1_unprepare,
-       .recalc_rate    = clk_pll2_recalc_rate,
-       .round_rate     = clk_pll2_round_rate,
-       .set_rate       = clk_pll2_set_rate,
+static const struct clk_ops clk_sccg_pll_ops = {
+       .prepare        = clk_sccg_pll_prepare,
+       .unprepare      = clk_sccg_pll_unprepare,
+       .is_prepared    = clk_sccg_pll_is_prepared,
+       .recalc_rate    = clk_sccg_pll_recalc_rate,
+       .set_rate       = clk_sccg_pll_set_rate,
+       .set_parent     = clk_sccg_pll_set_parent,
+       .get_parent     = clk_sccg_pll_get_parent,
+       .determine_rate = clk_sccg_pll_determine_rate,
 };
 
 struct clk *imx_clk_sccg_pll(const char *name,
-                               const char *parent_name,
+                               const char * const *parent_names,
+                               u8 num_parents,
+                               u8 parent, u8 bypass1, u8 bypass2,
                                void __iomem *base,
-                               enum imx_sccg_pll_type pll_type)
+                               unsigned long flags)
 {
        struct clk_sccg_pll *pll;
        struct clk_init_data init;
        struct clk_hw *hw;
        int ret;
 
-       switch (pll_type) {
-       case SCCG_PLL1:
-               init.ops = &clk_sccg_pll1_ops;
-               break;
-       case SCCG_PLL2:
-               init.ops = &clk_sccg_pll2_ops;
-               break;
-       default:
-               return ERR_PTR(-EINVAL);
-       }
-
        pll = kzalloc(sizeof(*pll), GFP_KERNEL);
        if (!pll)
                return ERR_PTR(-ENOMEM);
 
+       pll->parent = parent;
+       pll->bypass1 = bypass1;
+       pll->bypass2 = bypass2;
+
+       pll->base = base;
        init.name = name;
-       init.flags = 0;
-       init.parent_names = &parent_name;
-       init.num_parents = 1;
+       init.ops = &clk_sccg_pll_ops;
+
+       init.flags = flags;
+       init.parent_names = parent_names;
+       init.num_parents = num_parents;
 
        pll->base = base;
        pll->hw.init = &init;
index 7ccf7ed..fbef740 100644 (file)
@@ -4,12 +4,17 @@
  *   Dong Aisheng <aisheng.dong@nxp.com>
  */
 
+#include <dt-bindings/firmware/imx/rsrc.h>
+#include <linux/arm-smccc.h>
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/slab.h>
 
 #include "clk-scu.h"
 
+#define IMX_SIP_CPUFREQ                        0xC2000001
+#define IMX_SIP_SET_CPUFREQ            0x00
+
 static struct imx_sc_ipc *ccm_ipc_handle;
 
 /*
@@ -65,6 +70,41 @@ struct imx_sc_msg_get_clock_rate {
        } data;
 };
 
+/*
+ * struct imx_sc_msg_get_clock_parent - clock get parent protocol
+ * @hdr: SCU protocol header
+ * @req: get parent request protocol
+ * @resp: get parent response protocol
+ *
+ * This structure describes the SCU protocol of clock get parent
+ */
+struct imx_sc_msg_get_clock_parent {
+       struct imx_sc_rpc_msg hdr;
+       union {
+               struct req_get_clock_parent {
+                       __le16 resource;
+                       u8 clk;
+               } __packed req;
+               struct resp_get_clock_parent {
+                       u8 parent;
+               } resp;
+       } data;
+};
+
+/*
+ * struct imx_sc_msg_set_clock_parent - clock set parent protocol
+ * @hdr: SCU protocol header
+ * @req: set parent request protocol
+ *
+ * This structure describes the SCU protocol of clock set parent
+ */
+struct imx_sc_msg_set_clock_parent {
+       struct imx_sc_rpc_msg hdr;
+       __le16 resource;
+       u8 clk;
+       u8 parent;
+} __packed;
+
 /*
  * struct imx_sc_msg_req_clock_enable - clock gate protocol
  * @hdr: SCU protocol header
@@ -145,6 +185,25 @@ static long clk_scu_round_rate(struct clk_hw *hw, unsigned long rate,
        return rate;
 }
 
+static int clk_scu_atf_set_cpu_rate(struct clk_hw *hw, unsigned long rate,
+                                   unsigned long parent_rate)
+{
+       struct clk_scu *clk = to_clk_scu(hw);
+       struct arm_smccc_res res;
+       unsigned long cluster_id;
+
+       if (clk->rsrc_id == IMX_SC_R_A35)
+               cluster_id = 0;
+       else
+               return -EINVAL;
+
+       /* CPU frequency scaling can ONLY be done by ARM-Trusted-Firmware */
+       arm_smccc_smc(IMX_SIP_CPUFREQ, IMX_SIP_SET_CPUFREQ,
+                     cluster_id, rate, 0, 0, 0, 0, &res);
+
+       return 0;
+}
+
 /*
  * clk_scu_set_rate - Set rate for a SCU clock
  * @hw: clock to change rate for
@@ -173,6 +232,49 @@ static int clk_scu_set_rate(struct clk_hw *hw, unsigned long rate,
        return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
 }
 
+static u8 clk_scu_get_parent(struct clk_hw *hw)
+{
+       struct clk_scu *clk = to_clk_scu(hw);
+       struct imx_sc_msg_get_clock_parent msg;
+       struct imx_sc_rpc_msg *hdr = &msg.hdr;
+       int ret;
+
+       hdr->ver = IMX_SC_RPC_VERSION;
+       hdr->svc = IMX_SC_RPC_SVC_PM;
+       hdr->func = IMX_SC_PM_FUNC_GET_CLOCK_PARENT;
+       hdr->size = 2;
+
+       msg.data.req.resource = cpu_to_le16(clk->rsrc_id);
+       msg.data.req.clk = clk->clk_type;
+
+       ret = imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
+       if (ret) {
+               pr_err("%s: failed to get clock parent %d\n",
+                      clk_hw_get_name(hw), ret);
+               return 0;
+       }
+
+       return msg.data.resp.parent;
+}
+
+static int clk_scu_set_parent(struct clk_hw *hw, u8 index)
+{
+       struct clk_scu *clk = to_clk_scu(hw);
+       struct imx_sc_msg_set_clock_parent msg;
+       struct imx_sc_rpc_msg *hdr = &msg.hdr;
+
+       hdr->ver = IMX_SC_RPC_VERSION;
+       hdr->svc = IMX_SC_RPC_SVC_PM;
+       hdr->func = IMX_SC_PM_FUNC_SET_CLOCK_PARENT;
+       hdr->size = 2;
+
+       msg.resource = cpu_to_le16(clk->rsrc_id);
+       msg.clk = clk->clk_type;
+       msg.parent = index;
+
+       return imx_scu_call_rpc(ccm_ipc_handle, &msg, true);
+}
+
 static int sc_pm_clock_enable(struct imx_sc_ipc *ipc, u16 resource,
                              u8 clk, bool enable, bool autog)
 {
@@ -228,11 +330,22 @@ static const struct clk_ops clk_scu_ops = {
        .recalc_rate = clk_scu_recalc_rate,
        .round_rate = clk_scu_round_rate,
        .set_rate = clk_scu_set_rate,
+       .get_parent = clk_scu_get_parent,
+       .set_parent = clk_scu_set_parent,
+       .prepare = clk_scu_prepare,
+       .unprepare = clk_scu_unprepare,
+};
+
+static const struct clk_ops clk_scu_cpu_ops = {
+       .recalc_rate = clk_scu_recalc_rate,
+       .round_rate = clk_scu_round_rate,
+       .set_rate = clk_scu_atf_set_cpu_rate,
        .prepare = clk_scu_prepare,
        .unprepare = clk_scu_unprepare,
 };
 
-struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type)
+struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
+                            int num_parents, u32 rsrc_id, u8 clk_type)
 {
        struct clk_init_data init;
        struct clk_scu *clk;
@@ -248,7 +361,13 @@ struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type)
 
        init.name = name;
        init.ops = &clk_scu_ops;
-       init.num_parents = 0;
+       if (rsrc_id == IMX_SC_R_A35)
+               init.ops = &clk_scu_cpu_ops;
+       else
+               init.ops = &clk_scu_ops;
+       init.parent_names = parents;
+       init.num_parents = num_parents;
+
        /*
         * Note on MX8, the clocks are tightly coupled with power domain
         * that once the power domain is off, the clock status may be
index 52c1746..2bcfaf0 100644 (file)
 #include <linux/firmware/imx/sci.h>
 
 int imx_clk_scu_init(void);
-struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id, u8 clk_type);
+
+struct clk_hw *__imx_clk_scu(const char *name, const char * const *parents,
+                            int num_parents, u32 rsrc_id, u8 clk_type);
+
+static inline struct clk_hw *imx_clk_scu(const char *name, u32 rsrc_id,
+                                        u8 clk_type)
+{
+       return __imx_clk_scu(name, NULL, 0, rsrc_id, clk_type);
+}
+
+static inline struct clk_hw *imx_clk_scu2(const char *name, const char * const *parents,
+                                         int num_parents, u32 rsrc_id, u8 clk_type)
+{
+       return __imx_clk_scu(name, parents, num_parents, rsrc_id, clk_type);
+}
 
 struct clk_hw *imx_clk_lpcg_scu(const char *name, const char *parent_name,
                                unsigned long flags, void __iomem *reg,
index 6dae543..a334667 100644 (file)
@@ -203,6 +203,7 @@ static void __init vf610_clocks_init(struct device_node *ccm_node)
        np = of_find_compatible_node(NULL, NULL, "fsl,vf610-anatop");
        anatop_base = of_iomap(np, 0);
        BUG_ON(!anatop_base);
+       of_node_put(np);
 
        np = ccm_node;
        ccm_base = of_iomap(np, 0);
index 028312d..5748ec8 100644 (file)
@@ -27,6 +27,30 @@ enum imx_sccg_pll_type {
        SCCG_PLL2,
 };
 
+enum imx_pll14xx_type {
+       PLL_1416X,
+       PLL_1443X,
+};
+
+/* NOTE: Rate table should be kept sorted in descending order. */
+struct imx_pll14xx_rate_table {
+       unsigned int rate;
+       unsigned int pdiv;
+       unsigned int mdiv;
+       unsigned int sdiv;
+       unsigned int kdiv;
+};
+
+struct imx_pll14xx_clk {
+       enum imx_pll14xx_type type;
+       const struct imx_pll14xx_rate_table *rate_table;
+       int rate_count;
+       int flags;
+};
+
+struct clk *imx_clk_pll14xx(const char *name, const char *parent_name,
+                void __iomem *base, const struct imx_pll14xx_clk *pll_clk);
+
 struct clk *imx_clk_pllv1(enum imx_pllv1_type type, const char *name,
                const char *parent, void __iomem *base);
 
@@ -36,9 +60,12 @@ struct clk *imx_clk_pllv2(const char *name, const char *parent,
 struct clk *imx_clk_frac_pll(const char *name, const char *parent_name,
                             void __iomem *base);
 
-struct clk *imx_clk_sccg_pll(const char *name, const char *parent_name,
-                            void __iomem *base,
-                            enum imx_sccg_pll_type pll_type);
+struct clk *imx_clk_sccg_pll(const char *name,
+                               const char * const *parent_names,
+                               u8 num_parents,
+                               u8 parent, u8 bypass1, u8 bypass2,
+                               void __iomem *base,
+                               unsigned long flags);
 
 enum imx_pllv3_type {
        IMX_PLLV3_GENERIC,
@@ -329,7 +356,8 @@ static inline struct clk *imx_clk_mux_flags(const char *name,
 }
 
 static inline struct clk *imx_clk_mux2_flags(const char *name,
-               void __iomem *reg, u8 shift, u8 width, const char **parents,
+               void __iomem *reg, u8 shift, u8 width,
+               const char * const *parents,
                int num_parents, unsigned long flags)
 {
        return clk_register_mux(NULL, name, parents, num_parents,
@@ -354,7 +382,7 @@ struct clk *imx_clk_cpu(const char *name, const char *parent_name,
                struct clk *step);
 
 struct clk *imx8m_clk_composite_flags(const char *name,
-                                       const char **parent_names,
+                                       const char * const *parent_names,
                                        int num_parents, void __iomem *reg,
                                        unsigned long flags);
 
index 5ef7d9b..510b685 100644 (file)
@@ -83,7 +83,7 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
        const struct ingenic_cgu_clk_info *clk_info;
        const struct ingenic_cgu_pll_info *pll_info;
        unsigned m, n, od_enc, od;
-       bool bypass, enable;
+       bool bypass;
        unsigned long flags;
        u32 ctl;
 
@@ -103,7 +103,6 @@ ingenic_pll_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
        od_enc &= GENMASK(pll_info->od_bits - 1, 0);
        bypass = !pll_info->no_bypass_bit &&
                 !!(ctl & BIT(pll_info->bypass_bit));
-       enable = !!(ctl & BIT(pll_info->enable_bit));
 
        if (bypass)
                return parent_rate;
@@ -426,16 +425,16 @@ ingenic_clk_round_rate(struct clk_hw *hw, unsigned long req_rate,
        struct ingenic_clk *ingenic_clk = to_ingenic_clk(hw);
        struct ingenic_cgu *cgu = ingenic_clk->cgu;
        const struct ingenic_cgu_clk_info *clk_info;
-       long rate = *parent_rate;
+       unsigned int div = 1;
 
        clk_info = &cgu->clock_info[ingenic_clk->idx];
 
        if (clk_info->type & CGU_CLK_DIV)
-               rate /= ingenic_clk_calc_div(clk_info, *parent_rate, req_rate);
+               div = ingenic_clk_calc_div(clk_info, *parent_rate, req_rate);
        else if (clk_info->type & CGU_CLK_FIXDIV)
-               rate /= clk_info->fixdiv.div;
+               div = clk_info->fixdiv.div;
 
-       return rate;
+       return DIV_ROUND_UP(*parent_rate, div);
 }
 
 static int
@@ -455,7 +454,7 @@ ingenic_clk_set_rate(struct clk_hw *hw, unsigned long req_rate,
 
        if (clk_info->type & CGU_CLK_DIV) {
                div = ingenic_clk_calc_div(clk_info, parent_rate, req_rate);
-               rate = parent_rate / div;
+               rate = DIV_ROUND_UP(parent_rate, div);
 
                if (rate != req_rate)
                        return -EINVAL;
index 502bcbb..e12716d 100644 (file)
@@ -80,7 +80,7 @@ struct ingenic_cgu_mux_info {
  * @reg: offset of the divider control register within the CGU
  * @shift: number of bits to left shift the divide value by (ie. the index of
  *         the lowest bit of the divide value within its control register)
- * @div: number of bits to divide the divider value by (i.e. if the
+ * @div: number to divide the divider value by (i.e. if the
  *      effective divider value is the value written to the register
  *      multiplied by some constant)
  * @bits: the size of the divide value in bits
index 4479c10..b86edd3 100644 (file)
@@ -165,7 +165,7 @@ static const struct ingenic_cgu_clk_info jz4740_cgu_clocks[] = {
                .parents = { JZ4740_CLK_EXT, JZ4740_CLK_PLL_HALF, -1, -1 },
                .mux = { CGU_REG_CPCCR, 29, 1 },
                .div = { CGU_REG_CPCCR, 23, 1, 6, -1, -1, -1 },
-               .gate = { CGU_REG_SCR, 6 },
+               .gate = { CGU_REG_SCR, 6, true },
        },
 
        /* Gate-only clocks */
index 934bf0e..9628d4e 100644 (file)
@@ -157,7 +157,8 @@ struct clk *mtk_clk_register_gate(
                int clr_ofs,
                int sta_ofs,
                u8 bit,
-               const struct clk_ops *ops)
+               const struct clk_ops *ops,
+               unsigned long flags)
 {
        struct mtk_clk_gate *cg;
        struct clk *clk;
@@ -172,6 +173,7 @@ struct clk *mtk_clk_register_gate(
        init.parent_names = parent_name ? &parent_name : NULL;
        init.num_parents = parent_name ? 1 : 0;
        init.ops = ops;
+       init.flags = flags;
 
        cg->regmap = regmap;
        cg->set_ofs = set_ofs;
index 72ef89b..9f766df 100644 (file)
@@ -47,6 +47,7 @@ struct clk *mtk_clk_register_gate(
                int clr_ofs,
                int sta_ofs,
                u8 bit,
-               const struct clk_ops *ops);
+               const struct clk_ops *ops,
+               unsigned long flags);
 
 #endif /* __DRV_CLK_GATE_H */
index 991d409..2895a5a 100644 (file)
@@ -1463,7 +1463,6 @@ static struct platform_driver clk_mt2712_drv = {
        .probe = clk_mt2712_probe,
        .driver = {
                .name = "clk-mt2712",
-               .owner = THIS_MODULE,
                .of_match_table = of_match_clk_mt2712,
        },
 };
index 5702bc9..c2b46b1 100644 (file)
@@ -324,6 +324,10 @@ static const char * const anc_md32_parents[] = {
        "univpll_d5",
 };
 
+/*
+ * Clock mux ddrphycfg is needed by the DRAM controller. We mark it as
+ * critical as otherwise the system will hang after boot.
+ */
 static const struct mtk_composite top_muxes[] = {
        MUX(CLK_TOP_MUX_ULPOSC_AXI_CK_MUX_PRE, "ulposc_axi_ck_mux_pre",
            ulposc_axi_ck_mux_pre_parents, 0x0040, 3, 1),
@@ -331,8 +335,8 @@ static const struct mtk_composite top_muxes[] = {
            ulposc_axi_ck_mux_parents, 0x0040, 2, 1),
        MUX(CLK_TOP_MUX_AXI, "axi_sel", axi_parents,
            0x0040, 0, 2),
-       MUX(CLK_TOP_MUX_DDRPHYCFG, "ddrphycfg_sel", ddrphycfg_parents,
-           0x0040, 16, 2),
+       MUX_FLAGS(CLK_TOP_MUX_DDRPHYCFG, "ddrphycfg_sel", ddrphycfg_parents,
+                 0x0040, 16, 2, CLK_IS_CRITICAL | CLK_SET_RATE_PARENT),
        MUX(CLK_TOP_MUX_MM, "mm_sel", mm_parents,
            0x0040, 24, 2),
        MUX_GATE(CLK_TOP_MUX_PWM, "pwm_sel", pwm_parents, 0x0050, 0, 3, 7),
@@ -424,33 +428,45 @@ static const struct mtk_gate_regs infra2_cg_regs = {
        .sta_ofs = 0x00b0,
 };
 
-#define GATE_ICG0(_id, _name, _parent, _shift) {       \
-       .id = _id,                                      \
-       .name = _name,                                  \
-       .parent_name = _parent,                         \
-       .regs = &infra0_cg_regs,                        \
-       .shift = _shift,                                \
-       .ops = &mtk_clk_gate_ops_setclr,                \
+#define GATE_ICG0(_id, _name, _parent, _shift) {               \
+       .id = _id,                                              \
+       .name = _name,                                          \
+       .parent_name = _parent,                                 \
+       .regs = &infra0_cg_regs,                                \
+       .shift = _shift,                                        \
+       .ops = &mtk_clk_gate_ops_setclr,                        \
 }
 
-#define GATE_ICG1(_id, _name, _parent, _shift) {       \
-       .id = _id,                                      \
-       .name = _name,                                  \
-       .parent_name = _parent,                         \
-       .regs = &infra1_cg_regs,                        \
-       .shift = _shift,                                \
-       .ops = &mtk_clk_gate_ops_setclr,                \
+#define GATE_ICG1(_id, _name, _parent, _shift)                 \
+       GATE_ICG1_FLAGS(_id, _name, _parent, _shift, 0)
+
+#define GATE_ICG1_FLAGS(_id, _name, _parent, _shift, _flags) { \
+       .id = _id,                                              \
+       .name = _name,                                          \
+       .parent_name = _parent,                                 \
+       .regs = &infra1_cg_regs,                                \
+       .shift = _shift,                                        \
+       .ops = &mtk_clk_gate_ops_setclr,                        \
+       .flags = _flags,                                        \
 }
 
-#define GATE_ICG2(_id, _name, _parent, _shift) {       \
-       .id = _id,                                      \
-       .name = _name,                                  \
-       .parent_name = _parent,                         \
-       .regs = &infra2_cg_regs,                        \
-       .shift = _shift,                                \
-       .ops = &mtk_clk_gate_ops_setclr,                \
+#define GATE_ICG2(_id, _name, _parent, _shift)                 \
+       GATE_ICG2_FLAGS(_id, _name, _parent, _shift, 0)
+
+#define GATE_ICG2_FLAGS(_id, _name, _parent, _shift, _flags) { \
+       .id = _id,                                              \
+       .name = _name,                                          \
+       .parent_name = _parent,                                 \
+       .regs = &infra2_cg_regs,                                \
+       .shift = _shift,                                        \
+       .ops = &mtk_clk_gate_ops_setclr,                        \
+       .flags = _flags,                                        \
 }
 
+/*
+ * Clock gates dramc and dramc_b are needed by the DRAM controller.
+ * We mark them as critical as otherwise the system will hang after boot.
+ */
 static const struct mtk_gate infra_clks[] = {
        GATE_ICG0(CLK_INFRA_PMIC_TMR, "infra_pmic_tmr", "ulposc", 0),
        GATE_ICG0(CLK_INFRA_PMIC_AP, "infra_pmic_ap", "pmicspi_sel", 1),
@@ -505,7 +521,8 @@ static const struct mtk_gate infra_clks[] = {
        GATE_ICG1(CLK_INFRA_CCIF_AP, "infra_ccif_ap", "axi_sel", 23),
        GATE_ICG1(CLK_INFRA_AUDIO, "infra_audio", "axi_sel", 25),
        GATE_ICG1(CLK_INFRA_CCIF_MD, "infra_ccif_md", "axi_sel", 26),
-       GATE_ICG1(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m", "clk26m", 31),
+       GATE_ICG1_FLAGS(CLK_INFRA_DRAMC_F26M, "infra_dramc_f26m",
+                       "clk26m", 31, CLK_IS_CRITICAL),
        GATE_ICG2(CLK_INFRA_I2C4, "infra_i2c4", "axi_sel", 0),
        GATE_ICG2(CLK_INFRA_I2C_APPM, "infra_i2c_appm", "axi_sel", 1),
        GATE_ICG2(CLK_INFRA_I2C_GPUPM, "infra_i2c_gpupm", "axi_sel", 2),
@@ -516,7 +533,8 @@ static const struct mtk_gate infra_clks[] = {
        GATE_ICG2(CLK_INFRA_I2C5, "infra_i2c5", "axi_sel", 7),
        GATE_ICG2(CLK_INFRA_SYS_CIRQ, "infra_sys_cirq", "axi_sel", 8),
        GATE_ICG2(CLK_INFRA_SPI1, "infra_spi1", "spi_sel", 10),
-       GATE_ICG2(CLK_INFRA_DRAMC_B_F26M, "infra_dramc_b_f26m", "clk26m", 11),
+       GATE_ICG2_FLAGS(CLK_INFRA_DRAMC_B_F26M, "infra_dramc_b_f26m",
+                       "clk26m", 11, CLK_IS_CRITICAL),
        GATE_ICG2(CLK_INFRA_ANC_MD32, "infra_anc_md32", "anc_md32_sel", 12),
        GATE_ICG2(CLK_INFRA_ANC_MD32_32K, "infra_anc_md32_32k", "clk26m", 13),
        GATE_ICG2(CLK_INFRA_DVFS_SPM1, "infra_dvfs_spm1", "axi_sel", 15),
index 96c292c..deedeb3 100644 (file)
@@ -533,7 +533,7 @@ static const char * const ca53_parents[] __initconst = {
        "univpll"
 };
 
-static const char * const ca57_parents[] __initconst = {
+static const char * const ca72_parents[] __initconst = {
        "clk26m",
        "armca15pll",
        "mainpll",
@@ -542,7 +542,7 @@ static const char * const ca57_parents[] __initconst = {
 
 static const struct mtk_composite cpu_muxes[] __initconst = {
        MUX(CLK_INFRA_CA53SEL, "infra_ca53_sel", ca53_parents, 0x0000, 0, 2),
-       MUX(CLK_INFRA_CA57SEL, "infra_ca57_sel", ca57_parents, 0x0000, 2, 2),
+       MUX(CLK_INFRA_CA72SEL, "infra_ca72_sel", ca72_parents, 0x0000, 2, 2),
 };
 
 static const struct mtk_composite top_muxes[] __initconst = {
index 2ed9964..5531dd2 100644 (file)
@@ -130,7 +130,7 @@ int mtk_clk_register_gates(struct device_node *node,
                                gate->regs->set_ofs,
                                gate->regs->clr_ofs,
                                gate->regs->sta_ofs,
-                               gate->shift, gate->ops);
+                               gate->shift, gate->ops, gate->flags);
 
                if (IS_ERR(clk)) {
                        pr_err("Failed to register clk %s: %ld\n",
index 5f0b18b..fb27b5b 100644 (file)
@@ -119,7 +119,11 @@ struct mtk_composite {
        MUX_GATE_FLAGS(_id, _name, _parents, _reg, _shift, _width,      \
                _gate, CLK_SET_RATE_PARENT)
 
-#define MUX(_id, _name, _parents, _reg, _shift, _width) {              \
+#define MUX(_id, _name, _parents, _reg, _shift, _width)                        \
+       MUX_FLAGS(_id, _name, _parents, _reg,                           \
+                 _shift, _width, CLK_SET_RATE_PARENT)
+
+#define MUX_FLAGS(_id, _name, _parents, _reg, _shift, _width, _flags) {        \
                .id = _id,                                              \
                .name = _name,                                          \
                .mux_reg = _reg,                                        \
@@ -129,7 +133,7 @@ struct mtk_composite {
                .divider_shift = -1,                                    \
                .parent_names = _parents,                               \
                .num_parents = ARRAY_SIZE(_parents),                    \
-               .flags = CLK_SET_RATE_PARENT,                           \
+               .flags = _flags,                                \
        }
 
 #define DIV_GATE(_id, _name, _parent, _gate_reg, _gate_shift, _div_reg,        \
@@ -166,6 +170,7 @@ struct mtk_gate {
        const struct mtk_gate_regs *regs;
        int shift;
        const struct clk_ops *ops;
+       unsigned long flags;
 };
 
 int mtk_clk_register_gates(struct device_node *node,
index efaa70f..3858747 100644 (file)
@@ -1,27 +1,52 @@
-config COMMON_CLK_AMLOGIC
-       bool
-       depends on ARCH_MESON || COMPILE_TEST
-       select COMMON_CLK_REGMAP_MESON
+config COMMON_CLK_MESON_INPUT
+       tristate
 
-config COMMON_CLK_AMLOGIC_AUDIO
-       bool
-       depends on ARCH_MESON || COMPILE_TEST
-       select COMMON_CLK_AMLOGIC
+config COMMON_CLK_MESON_REGMAP
+       tristate
+       select REGMAP
 
-config COMMON_CLK_MESON_AO
-       bool
-       depends on OF
-       depends on ARCH_MESON || COMPILE_TEST
-       select COMMON_CLK_REGMAP_MESON
+config COMMON_CLK_MESON_DUALDIV
+       tristate
+       select COMMON_CLK_MESON_REGMAP
+
+config COMMON_CLK_MESON_MPLL
+       tristate
+       select COMMON_CLK_MESON_REGMAP
+
+config COMMON_CLK_MESON_PHASE
+       tristate
+       select COMMON_CLK_MESON_REGMAP
+
+config COMMON_CLK_MESON_PLL
+       tristate
+       select COMMON_CLK_MESON_REGMAP
+
+config COMMON_CLK_MESON_SCLK_DIV
+       tristate
+       select COMMON_CLK_MESON_REGMAP
+
+config COMMON_CLK_MESON_VID_PLL_DIV
+       tristate
+       select COMMON_CLK_MESON_REGMAP
+
+config COMMON_CLK_MESON_AO_CLKC
+       tristate
+       select COMMON_CLK_MESON_REGMAP
+       select COMMON_CLK_MESON_INPUT
        select RESET_CONTROLLER
 
-config COMMON_CLK_REGMAP_MESON
-       bool
-       select REGMAP
+config COMMON_CLK_MESON_EE_CLKC
+       tristate
+       select COMMON_CLK_MESON_REGMAP
+       select COMMON_CLK_MESON_INPUT
 
 config COMMON_CLK_MESON8B
        bool
-       select COMMON_CLK_AMLOGIC
+       depends on ARCH_MESON
+       select COMMON_CLK_MESON_REGMAP
+       select COMMON_CLK_MESON_MPLL
+       select COMMON_CLK_MESON_PLL
+       select MFD_SYSCON
        select RESET_CONTROLLER
        help
          Support for the clock controller on AmLogic S802 (Meson8),
@@ -30,8 +55,14 @@ config COMMON_CLK_MESON8B
 
 config COMMON_CLK_GXBB
        bool
-       select COMMON_CLK_AMLOGIC
-       select COMMON_CLK_MESON_AO
+       depends on ARCH_MESON
+       select COMMON_CLK_MESON_REGMAP
+       select COMMON_CLK_MESON_DUALDIV
+       select COMMON_CLK_MESON_VID_PLL_DIV
+       select COMMON_CLK_MESON_MPLL
+       select COMMON_CLK_MESON_PLL
+       select COMMON_CLK_MESON_AO_CLKC
+       select COMMON_CLK_MESON_EE_CLKC
        select MFD_SYSCON
        help
          Support for the clock controller on AmLogic S905 devices, aka gxbb.
@@ -39,8 +70,13 @@ config COMMON_CLK_GXBB
 
 config COMMON_CLK_AXG
        bool
-       select COMMON_CLK_AMLOGIC
-       select COMMON_CLK_MESON_AO
+       depends on ARCH_MESON
+       select COMMON_CLK_MESON_REGMAP
+       select COMMON_CLK_MESON_DUALDIV
+       select COMMON_CLK_MESON_MPLL
+       select COMMON_CLK_MESON_PLL
+       select COMMON_CLK_MESON_AO_CLKC
+       select COMMON_CLK_MESON_EE_CLKC
        select MFD_SYSCON
        help
          Support for the clock controller on AmLogic A113D devices, aka axg.
@@ -48,9 +84,26 @@ config COMMON_CLK_AXG
 
 config COMMON_CLK_AXG_AUDIO
        tristate "Meson AXG Audio Clock Controller Driver"
-       depends on COMMON_CLK_AXG
-       select COMMON_CLK_AMLOGIC_AUDIO
-       select MFD_SYSCON
+       depends on ARCH_MESON
+       select COMMON_CLK_MESON_INPUT
+       select COMMON_CLK_MESON_REGMAP
+       select COMMON_CLK_MESON_PHASE
+       select COMMON_CLK_MESON_SCLK_DIV
+       select REGMAP_MMIO
        help
          Support for the audio clock controller on AmLogic A113D devices,
          aka axg, Say Y if you want audio subsystem to work.
+
+config COMMON_CLK_G12A
+       bool
+       depends on ARCH_MESON
+       select COMMON_CLK_MESON_REGMAP
+       select COMMON_CLK_MESON_DUALDIV
+       select COMMON_CLK_MESON_MPLL
+       select COMMON_CLK_MESON_PLL
+       select COMMON_CLK_MESON_AO_CLKC
+       select COMMON_CLK_MESON_EE_CLKC
+       select MFD_SYSCON
+       help
+         Support for the clock controller on Amlogic S905D2, S905X2 and S905Y2
+         devices, aka g12a. Say Y if you want peripherals to work.
index a849aa8..021fc29 100644 (file)
@@ -1,13 +1,20 @@
-#
-# Makefile for Meson specific clk
-#
+# Amlogic clock drivers
 
-obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-pll.o clk-mpll.o clk-phase.o vid-pll-div.o
-obj-$(CONFIG_COMMON_CLK_AMLOGIC) += clk-input.o
-obj-$(CONFIG_COMMON_CLK_AMLOGIC_AUDIO) += clk-triphase.o sclk-div.o
-obj-$(CONFIG_COMMON_CLK_MESON_AO) += meson-aoclk.o
+obj-$(CONFIG_COMMON_CLK_MESON_AO_CLKC) += meson-aoclk.o
+obj-$(CONFIG_COMMON_CLK_MESON_DUALDIV) += clk-dualdiv.o
+obj-$(CONFIG_COMMON_CLK_MESON_EE_CLKC) += meson-eeclk.o
+obj-$(CONFIG_COMMON_CLK_MESON_INPUT) += clk-input.o
+obj-$(CONFIG_COMMON_CLK_MESON_MPLL) += clk-mpll.o
+obj-$(CONFIG_COMMON_CLK_MESON_PHASE) += clk-phase.o
+obj-$(CONFIG_COMMON_CLK_MESON_PLL) += clk-pll.o
+obj-$(CONFIG_COMMON_CLK_MESON_REGMAP) += clk-regmap.o
+obj-$(CONFIG_COMMON_CLK_MESON_SCLK_DIV) += sclk-div.o
+obj-$(CONFIG_COMMON_CLK_MESON_VID_PLL_DIV) += vid-pll-div.o
+
+# Amlogic Clock controllers
+
+obj-$(CONFIG_COMMON_CLK_AXG) += axg.o axg-aoclk.o
+obj-$(CONFIG_COMMON_CLK_AXG_AUDIO) += axg-audio.o
+obj-$(CONFIG_COMMON_CLK_GXBB) += gxbb.o gxbb-aoclk.o
+obj-$(CONFIG_COMMON_CLK_G12A) += g12a.o g12a-aoclk.o
 obj-$(CONFIG_COMMON_CLK_MESON8B) += meson8b.o
-obj-$(CONFIG_COMMON_CLK_GXBB)   += gxbb.o gxbb-aoclk.o gxbb-aoclk-32k.o
-obj-$(CONFIG_COMMON_CLK_AXG)    += axg.o axg-aoclk.o
-obj-$(CONFIG_COMMON_CLK_AXG_AUDIO)     += axg-audio.o
-obj-$(CONFIG_COMMON_CLK_REGMAP_MESON)  += clk-regmap.o
index 29e0885..0086f31 100644 (file)
 #include <linux/platform_device.h>
 #include <linux/reset-controller.h>
 #include <linux/mfd/syscon.h>
-#include "clk-regmap.h"
 #include "meson-aoclk.h"
 #include "axg-aoclk.h"
 
+#include "clk-regmap.h"
+#include "clk-dualdiv.h"
+
+#define IN_PREFIX "ao-in-"
+
+/*
+ * AO Configuration Clock registers offsets
+ * Register offsets from the data sheet must be multiplied by 4.
+ */
+#define AO_RTI_PWR_CNTL_REG1   0x0C
+#define AO_RTI_PWR_CNTL_REG0   0x10
+#define AO_RTI_GEN_CNTL_REG0   0x40
+#define AO_OSCIN_CNTL          0x58
+#define AO_CRT_CLK_CNTL1       0x68
+#define AO_SAR_CLK             0x90
+#define AO_RTC_ALT_CLK_CNTL0   0x94
+#define AO_RTC_ALT_CLK_CNTL1   0x98
+
 #define AXG_AO_GATE(_name, _bit)                                       \
 static struct clk_regmap axg_aoclk_##_name = {                         \
        .data = &(struct clk_regmap_gate_data) {                        \
@@ -25,7 +42,7 @@ static struct clk_regmap axg_aoclk_##_name = {                                \
        .hw.init = &(struct clk_init_data) {                            \
                .name =  "axg_ao_" #_name,                              \
                .ops = &clk_regmap_gate_ops,                            \
-               .parent_names = (const char *[]){ "clk81" },            \
+               .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \
                .num_parents = 1,                                       \
                .flags = CLK_IGNORE_UNUSED,                             \
        },                                                              \
@@ -39,17 +56,141 @@ AXG_AO_GATE(uart2, 5);
 AXG_AO_GATE(ir_blaster, 6);
 AXG_AO_GATE(saradc, 7);
 
+static struct clk_regmap axg_aoclk_cts_oscin = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = AO_RTI_PWR_CNTL_REG0,
+               .bit_idx = 14,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cts_oscin",
+               .ops = &clk_regmap_gate_ro_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap axg_aoclk_32k_pre = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = AO_RTC_ALT_CLK_CNTL0,
+               .bit_idx = 31,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "axg_ao_32k_pre",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "cts_oscin" },
+               .num_parents = 1,
+       },
+};
+
+static const struct meson_clk_dualdiv_param axg_32k_div_table[] = {
+       {
+               .dual   = 1,
+               .n1     = 733,
+               .m1     = 8,
+               .n2     = 732,
+               .m2     = 11,
+       }, {}
+};
+
+static struct clk_regmap axg_aoclk_32k_div = {
+       .data = &(struct meson_clk_dualdiv_data){
+               .n1 = {
+                       .reg_off = AO_RTC_ALT_CLK_CNTL0,
+                       .shift   = 0,
+                       .width   = 12,
+               },
+               .n2 = {
+                       .reg_off = AO_RTC_ALT_CLK_CNTL0,
+                       .shift   = 12,
+                       .width   = 12,
+               },
+               .m1 = {
+                       .reg_off = AO_RTC_ALT_CLK_CNTL1,
+                       .shift   = 0,
+                       .width   = 12,
+               },
+               .m2 = {
+                       .reg_off = AO_RTC_ALT_CLK_CNTL1,
+                       .shift   = 12,
+                       .width   = 12,
+               },
+               .dual = {
+                       .reg_off = AO_RTC_ALT_CLK_CNTL0,
+                       .shift   = 28,
+                       .width   = 1,
+               },
+               .table = axg_32k_div_table,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "axg_ao_32k_div",
+               .ops = &meson_clk_dualdiv_ops,
+               .parent_names = (const char *[]){ "axg_ao_32k_pre" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap axg_aoclk_32k_sel = {
+       .data = &(struct clk_regmap_mux_data) {
+               .offset = AO_RTC_ALT_CLK_CNTL1,
+               .mask = 0x1,
+               .shift = 24,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "axg_ao_32k_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = (const char *[]){ "axg_ao_32k_div",
+                                                 "axg_ao_32k_pre" },
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap axg_aoclk_32k = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = AO_RTC_ALT_CLK_CNTL0,
+               .bit_idx = 30,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "axg_ao_32k",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "axg_ao_32k_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap axg_aoclk_cts_rtc_oscin = {
+       .data = &(struct clk_regmap_mux_data) {
+               .offset = AO_RTI_PWR_CNTL_REG0,
+               .mask = 0x1,
+               .shift = 10,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "axg_ao_cts_rtc_oscin",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = (const char *[]){ "axg_ao_32k",
+                                                 IN_PREFIX "ext_32k-0" },
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
 static struct clk_regmap axg_aoclk_clk81 = {
        .data = &(struct clk_regmap_mux_data) {
                .offset = AO_RTI_PWR_CNTL_REG0,
                .mask = 0x1,
                .shift = 8,
+               .flags = CLK_MUX_ROUND_CLOSEST,
        },
        .hw.init = &(struct clk_init_data){
                .name = "axg_ao_clk81",
                .ops = &clk_regmap_mux_ro_ops,
-               .parent_names = (const char *[]){ "clk81", "ao_alt_xtal"},
+               .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk",
+                                                 "axg_ao_cts_rtc_oscin"},
                .num_parents = 2,
+               .flags = CLK_SET_RATE_PARENT,
        },
 };
 
@@ -62,7 +203,8 @@ static struct clk_regmap axg_aoclk_saradc_mux = {
        .hw.init = &(struct clk_init_data){
                .name = "axg_ao_saradc_mux",
                .ops = &clk_regmap_mux_ops,
-               .parent_names = (const char *[]){ "xtal", "axg_ao_clk81" },
+               .parent_names = (const char *[]){ IN_PREFIX "xtal",
+                                                 "axg_ao_clk81" },
                .num_parents = 2,
        },
 };
@@ -106,17 +248,23 @@ static const unsigned int axg_aoclk_reset[] = {
 };
 
 static struct clk_regmap *axg_aoclk_regmap[] = {
-       [CLKID_AO_REMOTE]       = &axg_aoclk_remote,
-       [CLKID_AO_I2C_MASTER]   = &axg_aoclk_i2c_master,
-       [CLKID_AO_I2C_SLAVE]    = &axg_aoclk_i2c_slave,
-       [CLKID_AO_UART1]        = &axg_aoclk_uart1,
-       [CLKID_AO_UART2]        = &axg_aoclk_uart2,
-       [CLKID_AO_IR_BLASTER]   = &axg_aoclk_ir_blaster,
-       [CLKID_AO_SAR_ADC]      = &axg_aoclk_saradc,
-       [CLKID_AO_CLK81]        = &axg_aoclk_clk81,
-       [CLKID_AO_SAR_ADC_SEL]  = &axg_aoclk_saradc_mux,
-       [CLKID_AO_SAR_ADC_DIV]  = &axg_aoclk_saradc_div,
-       [CLKID_AO_SAR_ADC_CLK]  = &axg_aoclk_saradc_gate,
+       &axg_aoclk_remote,
+       &axg_aoclk_i2c_master,
+       &axg_aoclk_i2c_slave,
+       &axg_aoclk_uart1,
+       &axg_aoclk_uart2,
+       &axg_aoclk_ir_blaster,
+       &axg_aoclk_saradc,
+       &axg_aoclk_cts_oscin,
+       &axg_aoclk_32k_pre,
+       &axg_aoclk_32k_div,
+       &axg_aoclk_32k_sel,
+       &axg_aoclk_32k,
+       &axg_aoclk_cts_rtc_oscin,
+       &axg_aoclk_clk81,
+       &axg_aoclk_saradc_mux,
+       &axg_aoclk_saradc_div,
+       &axg_aoclk_saradc_gate,
 };
 
 static const struct clk_hw_onecell_data axg_aoclk_onecell_data = {
@@ -132,10 +280,22 @@ static const struct clk_hw_onecell_data axg_aoclk_onecell_data = {
                [CLKID_AO_SAR_ADC_SEL]  = &axg_aoclk_saradc_mux.hw,
                [CLKID_AO_SAR_ADC_DIV]  = &axg_aoclk_saradc_div.hw,
                [CLKID_AO_SAR_ADC_CLK]  = &axg_aoclk_saradc_gate.hw,
+               [CLKID_AO_CTS_OSCIN]    = &axg_aoclk_cts_oscin.hw,
+               [CLKID_AO_32K_PRE]      = &axg_aoclk_32k_pre.hw,
+               [CLKID_AO_32K_DIV]      = &axg_aoclk_32k_div.hw,
+               [CLKID_AO_32K_SEL]      = &axg_aoclk_32k_sel.hw,
+               [CLKID_AO_32K]          = &axg_aoclk_32k.hw,
+               [CLKID_AO_CTS_RTC_OSCIN] = &axg_aoclk_cts_rtc_oscin.hw,
        },
        .num = NR_CLKS,
 };
 
+static const struct meson_aoclk_input axg_aoclk_inputs[] = {
+       { .name = "xtal",       .required = true  },
+       { .name = "mpeg-clk",   .required = true  },
+       { .name = "ext-32k-0",  .required = false },
+};
+
 static const struct meson_aoclk_data axg_aoclkc_data = {
        .reset_reg      = AO_RTI_GEN_CNTL_REG0,
        .num_reset      = ARRAY_SIZE(axg_aoclk_reset),
@@ -143,6 +303,9 @@ static const struct meson_aoclk_data axg_aoclkc_data = {
        .num_clks       = ARRAY_SIZE(axg_aoclk_regmap),
        .clks           = axg_aoclk_regmap,
        .hw_data        = &axg_aoclk_onecell_data,
+       .inputs         = axg_aoclk_inputs,
+       .num_inputs     = ARRAY_SIZE(axg_aoclk_inputs),
+       .input_prefix   = IN_PREFIX,
 };
 
 static const struct of_device_id axg_aoclkc_match_table[] = {
index 91384d8..3cc27e8 100644 (file)
 #ifndef __AXG_AOCLKC_H
 #define __AXG_AOCLKC_H
 
-#define NR_CLKS        11
-/* AO Configuration Clock registers offsets
- * Register offsets from the data sheet must be multiplied by 4.
- */
-#define AO_RTI_PWR_CNTL_REG1   0x0C
-#define AO_RTI_PWR_CNTL_REG0   0x10
-#define AO_RTI_GEN_CNTL_REG0   0x40
-#define AO_OSCIN_CNTL          0x58
-#define AO_CRT_CLK_CNTL1       0x68
-#define AO_SAR_CLK             0x90
-#define AO_RTC_ALT_CLK_CNTL0   0x94
-#define AO_RTC_ALT_CLK_CNTL1   0x98
+#define NR_CLKS        17
 
 #include <dt-bindings/clock/axg-aoclkc.h>
 #include <dt-bindings/reset/axg-aoclkc.h>
index 8ac3a22..7ab200b 100644 (file)
 #include <linux/reset.h>
 #include <linux/slab.h>
 
-#include "clkc-audio.h"
 #include "axg-audio.h"
+#include "clk-input.h"
+#include "clk-regmap.h"
+#include "clk-phase.h"
+#include "sclk-div.h"
 
 #define AXG_MST_IN_COUNT       8
 #define AXG_SLV_SCLK_COUNT     10
index 792735d..7a8ef80 100644 (file)
@@ -9,16 +9,17 @@
  * Author: Qiufang Dai <qiufang.dai@amlogic.com>
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/init.h>
 #include <linux/of_device.h>
-#include <linux/mfd/syscon.h>
 #include <linux/platform_device.h>
-#include <linux/regmap.h>
 
-#include "clkc.h"
+#include "clk-input.h"
+#include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-mpll.h"
 #include "axg.h"
+#include "meson-eeclk.h"
 
 static DEFINE_SPINLOCK(meson_clk_lock);
 
@@ -58,7 +59,7 @@ static struct clk_regmap axg_fixed_pll_dco = {
        .hw.init = &(struct clk_init_data){
                .name = "fixed_pll_dco",
                .ops = &meson_clk_pll_ro_ops,
-               .parent_names = (const char *[]){ "xtal" },
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
                .num_parents = 1,
        },
 };
@@ -113,7 +114,7 @@ static struct clk_regmap axg_sys_pll_dco = {
        .hw.init = &(struct clk_init_data){
                .name = "sys_pll_dco",
                .ops = &meson_clk_pll_ro_ops,
-               .parent_names = (const char *[]){ "xtal" },
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
                .num_parents = 1,
        },
 };
@@ -214,7 +215,7 @@ static struct clk_regmap axg_gp0_pll_dco = {
        .hw.init = &(struct clk_init_data){
                .name = "gp0_pll_dco",
                .ops = &meson_clk_pll_ops,
-               .parent_names = (const char *[]){ "xtal" },
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
                .num_parents = 1,
        },
 };
@@ -283,7 +284,7 @@ static struct clk_regmap axg_hifi_pll_dco = {
        .hw.init = &(struct clk_init_data){
                .name = "hifi_pll_dco",
                .ops = &meson_clk_pll_ops,
-               .parent_names = (const char *[]){ "xtal" },
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
                .num_parents = 1,
        },
 };
@@ -701,7 +702,7 @@ static struct clk_regmap axg_pcie_pll_dco = {
        .hw.init = &(struct clk_init_data){
                .name = "pcie_pll_dco",
                .ops = &meson_clk_pll_ops,
-               .parent_names = (const char *[]){ "xtal" },
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
                .num_parents = 1,
        },
 };
@@ -803,7 +804,7 @@ static struct clk_regmap axg_pcie_cml_en1 = {
 
 static u32 mux_table_clk81[]   = { 0, 2, 3, 4, 5, 6, 7 };
 static const char * const clk81_parent_names[] = {
-       "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
+       IN_PREFIX "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
        "fclk_div3", "fclk_div5"
 };
 
@@ -852,7 +853,7 @@ static struct clk_regmap axg_clk81 = {
 };
 
 static const char * const axg_sd_emmc_clk0_parent_names[] = {
-       "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7",
+       IN_PREFIX "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7",
 
        /*
         * Following these parent clocks, we should also have had mpll2, mpll3
@@ -957,7 +958,7 @@ static struct clk_regmap axg_sd_emmc_c_clk0 = {
 static u32 mux_table_gen_clk[] = { 0, 4, 5, 6, 7, 8,
                                    9, 10, 11, 13, 14, };
 static const char * const gen_clk_parent_names[] = {
-       "xtal", "hifi_pll", "mpll0", "mpll1", "mpll2", "mpll3",
+       IN_PREFIX "xtal", "hifi_pll", "mpll0", "mpll1", "mpll2", "mpll3",
        "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "gp0_pll",
 };
 
@@ -1255,46 +1256,20 @@ static struct clk_regmap *const axg_clk_regmaps[] = {
        &axg_pcie_pll_od,
 };
 
+static const struct meson_eeclkc_data axg_clkc_data = {
+       .regmap_clks = axg_clk_regmaps,
+       .regmap_clk_num = ARRAY_SIZE(axg_clk_regmaps),
+       .hw_onecell_data = &axg_hw_onecell_data,
+};
+
+
 static const struct of_device_id clkc_match_table[] = {
-       { .compatible = "amlogic,axg-clkc" },
+       { .compatible = "amlogic,axg-clkc", .data = &axg_clkc_data },
        {}
 };
 
-static int axg_clkc_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct regmap *map;
-       int ret, i;
-
-       /* Get the hhi system controller node if available */
-       map = syscon_node_to_regmap(of_get_parent(dev->of_node));
-       if (IS_ERR(map)) {
-               dev_err(dev, "failed to get HHI regmap\n");
-               return PTR_ERR(map);
-       }
-
-       /* Populate regmap for the regmap backed clocks */
-       for (i = 0; i < ARRAY_SIZE(axg_clk_regmaps); i++)
-               axg_clk_regmaps[i]->map = map;
-
-       for (i = 0; i < axg_hw_onecell_data.num; i++) {
-               /* array might be sparse */
-               if (!axg_hw_onecell_data.hws[i])
-                       continue;
-
-               ret = devm_clk_hw_register(dev, axg_hw_onecell_data.hws[i]);
-               if (ret) {
-                       dev_err(dev, "Clock registration failed\n");
-                       return ret;
-               }
-       }
-
-       return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
-                                          &axg_hw_onecell_data);
-}
-
 static struct platform_driver axg_driver = {
-       .probe          = axg_clkc_probe,
+       .probe          = meson_eeclkc_probe,
        .driver         = {
                .name   = "axg-clkc",
                .of_match_table = clkc_match_table,
diff --git a/drivers/clk/meson/clk-dualdiv.c b/drivers/clk/meson/clk-dualdiv.c
new file mode 100644 (file)
index 0000000..c5ca23a
--- /dev/null
@@ -0,0 +1,138 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2017 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+/*
+ * The AO Domain embeds a dual/divider to generate a more precise
+ * 32,768KHz clock for low-power suspend mode and CEC.
+ *     ______   ______
+ *    |      | |      |
+ *    | Div1 |-| Cnt1 |
+ *   /|______| |______|\
+ * -|  ______   ______  X--> Out
+ *   \|      | |      |/
+ *    | Div2 |-| Cnt2 |
+ *    |______| |______|
+ *
+ * The dividing can be switched to single or dual, with a counter
+ * for each divider to set when the switching is done.
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+
+#include "clk-regmap.h"
+#include "clk-dualdiv.h"
+
+static inline struct meson_clk_dualdiv_data *
+meson_clk_dualdiv_data(struct clk_regmap *clk)
+{
+       return (struct meson_clk_dualdiv_data *)clk->data;
+}
+
+static unsigned long
+__dualdiv_param_to_rate(unsigned long parent_rate,
+                       const struct meson_clk_dualdiv_param *p)
+{
+       if (!p->dual)
+               return DIV_ROUND_CLOSEST(parent_rate, p->n1);
+
+       return DIV_ROUND_CLOSEST(parent_rate * (p->m1 + p->m2),
+                                p->n1 * p->m1 + p->n2 * p->m2);
+}
+
+static unsigned long meson_clk_dualdiv_recalc_rate(struct clk_hw *hw,
+                                                  unsigned long parent_rate)
+{
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_dualdiv_data *dualdiv = meson_clk_dualdiv_data(clk);
+       struct meson_clk_dualdiv_param setting;
+
+       setting.dual = meson_parm_read(clk->map, &dualdiv->dual);
+       setting.n1 = meson_parm_read(clk->map, &dualdiv->n1) + 1;
+       setting.m1 = meson_parm_read(clk->map, &dualdiv->m1) + 1;
+       setting.n2 = meson_parm_read(clk->map, &dualdiv->n2) + 1;
+       setting.m2 = meson_parm_read(clk->map, &dualdiv->m2) + 1;
+
+       return __dualdiv_param_to_rate(parent_rate, &setting);
+}
+
+static const struct meson_clk_dualdiv_param *
+__dualdiv_get_setting(unsigned long rate, unsigned long parent_rate,
+                     struct meson_clk_dualdiv_data *dualdiv)
+{
+       const struct meson_clk_dualdiv_param *table = dualdiv->table;
+       unsigned long best = 0, now = 0;
+       unsigned int i, best_i = 0;
+
+       if (!table)
+               return NULL;
+
+       for (i = 0; table[i].n1; i++) {
+               now = __dualdiv_param_to_rate(parent_rate, &table[i]);
+
+               /* If we get an exact match, don't bother any further */
+               if (now == rate) {
+                       return &table[i];
+               } else if (abs(now - rate) < abs(best - rate)) {
+                       best = now;
+                       best_i = i;
+               }
+       }
+
+       return (struct meson_clk_dualdiv_param *)&table[best_i];
+}
+
+static long meson_clk_dualdiv_round_rate(struct clk_hw *hw, unsigned long rate,
+                                        unsigned long *parent_rate)
+{
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_dualdiv_data *dualdiv = meson_clk_dualdiv_data(clk);
+       const struct meson_clk_dualdiv_param *setting =
+               __dualdiv_get_setting(rate, *parent_rate, dualdiv);
+
+       if (!setting)
+               return meson_clk_dualdiv_recalc_rate(hw, *parent_rate);
+
+       return __dualdiv_param_to_rate(*parent_rate, setting);
+}
+
+static int meson_clk_dualdiv_set_rate(struct clk_hw *hw, unsigned long rate,
+                                     unsigned long parent_rate)
+{
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_dualdiv_data *dualdiv = meson_clk_dualdiv_data(clk);
+       const struct meson_clk_dualdiv_param *setting =
+               __dualdiv_get_setting(rate, parent_rate, dualdiv);
+
+       if (!setting)
+               return -EINVAL;
+
+       meson_parm_write(clk->map, &dualdiv->dual, setting->dual);
+       meson_parm_write(clk->map, &dualdiv->n1, setting->n1 - 1);
+       meson_parm_write(clk->map, &dualdiv->m1, setting->m1 - 1);
+       meson_parm_write(clk->map, &dualdiv->n2, setting->n2 - 1);
+       meson_parm_write(clk->map, &dualdiv->m2, setting->m2 - 1);
+
+       return 0;
+}
+
+const struct clk_ops meson_clk_dualdiv_ops = {
+       .recalc_rate    = meson_clk_dualdiv_recalc_rate,
+       .round_rate     = meson_clk_dualdiv_round_rate,
+       .set_rate       = meson_clk_dualdiv_set_rate,
+};
+EXPORT_SYMBOL_GPL(meson_clk_dualdiv_ops);
+
+const struct clk_ops meson_clk_dualdiv_ro_ops = {
+       .recalc_rate    = meson_clk_dualdiv_recalc_rate,
+};
+EXPORT_SYMBOL_GPL(meson_clk_dualdiv_ro_ops);
+
+MODULE_DESCRIPTION("Amlogic dual divider driver");
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/clk-dualdiv.h b/drivers/clk/meson/clk-dualdiv.h
new file mode 100644 (file)
index 0000000..4aa9390
--- /dev/null
@@ -0,0 +1,33 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+#ifndef __MESON_CLK_DUALDIV_H
+#define __MESON_CLK_DUALDIV_H
+
+#include <linux/clk-provider.h>
+#include "parm.h"
+
+struct meson_clk_dualdiv_param {
+       unsigned int n1;
+       unsigned int n2;
+       unsigned int m1;
+       unsigned int m2;
+       unsigned int dual;
+};
+
+struct meson_clk_dualdiv_data {
+       struct parm n1;
+       struct parm n2;
+       struct parm m1;
+       struct parm m2;
+       struct parm dual;
+       const struct meson_clk_dualdiv_param *table;
+};
+
+extern const struct clk_ops meson_clk_dualdiv_ops;
+extern const struct clk_ops meson_clk_dualdiv_ro_ops;
+
+#endif /* __MESON_CLK_DUALDIV_H */
index 06b3e3b..086226e 100644 (file)
@@ -7,7 +7,8 @@
 #include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/device.h>
-#include "clkc.h"
+#include <linux/module.h>
+#include "clk-input.h"
 
 static const struct clk_ops meson_clk_no_ops = {};
 
@@ -42,3 +43,7 @@ struct clk_hw *meson_clk_hw_register_input(struct device *dev,
        return ret ? ERR_PTR(ret) : hw;
 }
 EXPORT_SYMBOL_GPL(meson_clk_hw_register_input);
+
+MODULE_DESCRIPTION("Amlogic clock input helper");
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/clk-input.h b/drivers/clk/meson/clk-input.h
new file mode 100644 (file)
index 0000000..4a541b9
--- /dev/null
@@ -0,0 +1,19 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+#ifndef __MESON_CLK_INPUT_H
+#define __MESON_CLK_INPUT_H
+
+#include <linux/clk-provider.h>
+
+struct device;
+
+struct clk_hw *meson_clk_hw_register_input(struct device *dev,
+                                          const char *of_name,
+                                          const char *clk_name,
+                                          unsigned long flags);
+
+#endif /* __MESON_CLK_INPUT_H */
index 650f75c..f76850d 100644 (file)
  */
 
 #include <linux/clk-provider.h>
-#include "clkc.h"
+#include <linux/module.h>
+#include <linux/spinlock.h>
+
+#include "clk-regmap.h"
+#include "clk-mpll.h"
 
 #define SDM_DEN 16384
 #define N2_MIN 4
@@ -138,9 +142,15 @@ const struct clk_ops meson_clk_mpll_ro_ops = {
        .recalc_rate    = mpll_recalc_rate,
        .round_rate     = mpll_round_rate,
 };
+EXPORT_SYMBOL_GPL(meson_clk_mpll_ro_ops);
 
 const struct clk_ops meson_clk_mpll_ops = {
        .recalc_rate    = mpll_recalc_rate,
        .round_rate     = mpll_round_rate,
        .set_rate       = mpll_set_rate,
 };
+EXPORT_SYMBOL_GPL(meson_clk_mpll_ops);
+
+MODULE_DESCRIPTION("Amlogic MPLL driver");
+MODULE_AUTHOR("Michael Turquette <mturquette@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/clk-mpll.h b/drivers/clk/meson/clk-mpll.h
new file mode 100644 (file)
index 0000000..cf79340
--- /dev/null
@@ -0,0 +1,30 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+#ifndef __MESON_CLK_MPLL_H
+#define __MESON_CLK_MPLL_H
+
+#include <linux/clk-provider.h>
+#include <linux/spinlock.h>
+
+#include "parm.h"
+
+struct meson_clk_mpll_data {
+       struct parm sdm;
+       struct parm sdm_en;
+       struct parm n2;
+       struct parm ssen;
+       struct parm misc;
+       spinlock_t *lock;
+       u8 flags;
+};
+
+#define CLK_MESON_MPLL_ROUND_CLOSEST   BIT(0)
+
+extern const struct clk_ops meson_clk_mpll_ro_ops;
+extern const struct clk_ops meson_clk_mpll_ops;
+
+#endif /* __MESON_CLK_MPLL_H */
index cba4374..80c3ada 100644 (file)
@@ -5,7 +5,10 @@
  */
 
 #include <linux/clk-provider.h>
-#include "clkc.h"
+#include <linux/module.h>
+
+#include "clk-regmap.h"
+#include "clk-phase.h"
 
 #define phase_step(_width) (360 / (1 << (_width)))
 
@@ -15,13 +18,12 @@ meson_clk_phase_data(struct clk_regmap *clk)
        return (struct meson_clk_phase_data *)clk->data;
 }
 
-int meson_clk_degrees_from_val(unsigned int val, unsigned int width)
+static int meson_clk_degrees_from_val(unsigned int val, unsigned int width)
 {
        return phase_step(width) * val;
 }
-EXPORT_SYMBOL_GPL(meson_clk_degrees_from_val);
 
-unsigned int meson_clk_degrees_to_val(int degrees, unsigned int width)
+static unsigned int meson_clk_degrees_to_val(int degrees, unsigned int width)
 {
        unsigned int val = DIV_ROUND_CLOSEST(degrees, phase_step(width));
 
@@ -31,7 +33,6 @@ unsigned int meson_clk_degrees_to_val(int degrees, unsigned int width)
         */
        return val % (1 << width);
 }
-EXPORT_SYMBOL_GPL(meson_clk_degrees_to_val);
 
 static int meson_clk_phase_get_phase(struct clk_hw *hw)
 {
@@ -61,3 +62,67 @@ const struct clk_ops meson_clk_phase_ops = {
        .set_phase      = meson_clk_phase_set_phase,
 };
 EXPORT_SYMBOL_GPL(meson_clk_phase_ops);
+
+/*
+ * This is a special clock for the audio controller.
+ * The phase of mst_sclk clock output can be controlled independently
+ * for the outside world (ph0), the tdmout (ph1) and tdmin (ph2).
+ * Controlling these 3 phases as just one makes things simpler and
+ * give the same clock view to all the element on the i2s bus.
+ * If necessary, we can still control the phase in the tdm block
+ * which makes these independent control redundant.
+ */
+static inline struct meson_clk_triphase_data *
+meson_clk_triphase_data(struct clk_regmap *clk)
+{
+       return (struct meson_clk_triphase_data *)clk->data;
+}
+
+static void meson_clk_triphase_sync(struct clk_hw *hw)
+{
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk);
+       unsigned int val;
+
+       /* Get phase 0 and sync it to phase 1 and 2 */
+       val = meson_parm_read(clk->map, &tph->ph0);
+       meson_parm_write(clk->map, &tph->ph1, val);
+       meson_parm_write(clk->map, &tph->ph2, val);
+}
+
+static int meson_clk_triphase_get_phase(struct clk_hw *hw)
+{
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk);
+       unsigned int val;
+
+       /* Phase are in sync, reading phase 0 is enough */
+       val = meson_parm_read(clk->map, &tph->ph0);
+
+       return meson_clk_degrees_from_val(val, tph->ph0.width);
+}
+
+static int meson_clk_triphase_set_phase(struct clk_hw *hw, int degrees)
+{
+       struct clk_regmap *clk = to_clk_regmap(hw);
+       struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk);
+       unsigned int val;
+
+       val = meson_clk_degrees_to_val(degrees, tph->ph0.width);
+       meson_parm_write(clk->map, &tph->ph0, val);
+       meson_parm_write(clk->map, &tph->ph1, val);
+       meson_parm_write(clk->map, &tph->ph2, val);
+
+       return 0;
+}
+
+const struct clk_ops meson_clk_triphase_ops = {
+       .init           = meson_clk_triphase_sync,
+       .get_phase      = meson_clk_triphase_get_phase,
+       .set_phase      = meson_clk_triphase_set_phase,
+};
+EXPORT_SYMBOL_GPL(meson_clk_triphase_ops);
+
+MODULE_DESCRIPTION("Amlogic phase driver");
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/clk-phase.h b/drivers/clk/meson/clk-phase.h
new file mode 100644 (file)
index 0000000..5579f9c
--- /dev/null
@@ -0,0 +1,26 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+#ifndef __MESON_CLK_PHASE_H
+#define __MESON_CLK_PHASE_H
+
+#include <linux/clk-provider.h>
+#include "parm.h"
+
+struct meson_clk_phase_data {
+       struct parm ph;
+};
+
+struct meson_clk_triphase_data {
+       struct parm ph0;
+       struct parm ph1;
+       struct parm ph2;
+};
+
+extern const struct clk_ops meson_clk_phase_ops;
+extern const struct clk_ops meson_clk_triphase_ops;
+
+#endif /* __MESON_CLK_PHASE_H */
index afffc15..41e16dd 100644 (file)
 #include <linux/io.h>
 #include <linux/math64.h>
 #include <linux/module.h>
-#include <linux/of_address.h>
-#include <linux/slab.h>
-#include <linux/string.h>
+#include <linux/rational.h>
 
-#include "clkc.h"
+#include "clk-regmap.h"
+#include "clk-pll.h"
 
 static inline struct meson_clk_pll_data *
 meson_clk_pll_data(struct clk_regmap *clk)
@@ -44,12 +43,21 @@ meson_clk_pll_data(struct clk_regmap *clk)
        return (struct meson_clk_pll_data *)clk->data;
 }
 
+static int __pll_round_closest_mult(struct meson_clk_pll_data *pll)
+{
+       if ((pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) &&
+           !MESON_PARM_APPLICABLE(&pll->frac))
+               return 1;
+
+       return 0;
+}
+
 static unsigned long __pll_params_to_rate(unsigned long parent_rate,
-                                         const struct pll_params_table *pllt,
-                                         u16 frac,
+                                         unsigned int m, unsigned int n,
+                                         unsigned int frac,
                                          struct meson_clk_pll_data *pll)
 {
-       u64 rate = (u64)parent_rate * pllt->m;
+       u64 rate = (u64)parent_rate * m;
 
        if (frac && MESON_PARM_APPLICABLE(&pll->frac)) {
                u64 frac_rate = (u64)parent_rate * frac;
@@ -58,7 +66,7 @@ static unsigned long __pll_params_to_rate(unsigned long parent_rate,
                                         (1 << pll->frac.width));
        }
 
-       return DIV_ROUND_UP_ULL(rate, pllt->n);
+       return DIV_ROUND_UP_ULL(rate, n);
 }
 
 static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
@@ -66,35 +74,39 @@ static unsigned long meson_clk_pll_recalc_rate(struct clk_hw *hw,
 {
        struct clk_regmap *clk = to_clk_regmap(hw);
        struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
-       struct pll_params_table pllt;
-       u16 frac;
+       unsigned int m, n, frac;
 
-       pllt.n = meson_parm_read(clk->map, &pll->n);
-       pllt.m = meson_parm_read(clk->map, &pll->m);
+       n = meson_parm_read(clk->map, &pll->n);
+       m = meson_parm_read(clk->map, &pll->m);
 
        frac = MESON_PARM_APPLICABLE(&pll->frac) ?
                meson_parm_read(clk->map, &pll->frac) :
                0;
 
-       return __pll_params_to_rate(parent_rate, &pllt, frac, pll);
+       return __pll_params_to_rate(parent_rate, m, n, frac, pll);
 }
 
-static u16 __pll_params_with_frac(unsigned long rate,
-                                 unsigned long parent_rate,
-                                 const struct pll_params_table *pllt,
-                                 struct meson_clk_pll_data *pll)
+static unsigned int __pll_params_with_frac(unsigned long rate,
+                                          unsigned long parent_rate,
+                                          unsigned int m,
+                                          unsigned int n,
+                                          struct meson_clk_pll_data *pll)
 {
-       u16 frac_max = (1 << pll->frac.width);
-       u64 val = (u64)rate * pllt->n;
+       unsigned int frac_max = (1 << pll->frac.width);
+       u64 val = (u64)rate * n;
+
+       /* Bail out if we are already over the requested rate */
+       if (rate < parent_rate * m / n)
+               return 0;
 
        if (pll->flags & CLK_MESON_PLL_ROUND_CLOSEST)
                val = DIV_ROUND_CLOSEST_ULL(val * frac_max, parent_rate);
        else
                val = div_u64(val * frac_max, parent_rate);
 
-       val -= pllt->m * frac_max;
+       val -= m * frac_max;
 
-       return min((u16)val, (u16)(frac_max - 1));
+       return min((unsigned int)val, (frac_max - 1));
 }
 
 static bool meson_clk_pll_is_better(unsigned long rate,
@@ -102,45 +114,123 @@ static bool meson_clk_pll_is_better(unsigned long rate,
                                    unsigned long now,
                                    struct meson_clk_pll_data *pll)
 {
-       if (!(pll->flags & CLK_MESON_PLL_ROUND_CLOSEST) ||
-           MESON_PARM_APPLICABLE(&pll->frac)) {
-               /* Round down */
-               if (now < rate && best < now)
-                       return true;
-       } else {
+       if (__pll_round_closest_mult(pll)) {
                /* Round Closest */
                if (abs(now - rate) < abs(best - rate))
                        return true;
+       } else {
+               /* Round down */
+               if (now < rate && best < now)
+                       return true;
        }
 
        return false;
 }
 
-static const struct pll_params_table *
-meson_clk_get_pll_settings(unsigned long rate,
-                          unsigned long parent_rate,
-                          struct meson_clk_pll_data *pll)
+static int meson_clk_get_pll_table_index(unsigned int index,
+                                        unsigned int *m,
+                                        unsigned int *n,
+                                        struct meson_clk_pll_data *pll)
 {
-       const struct pll_params_table *table = pll->table;
-       unsigned long best = 0, now = 0;
-       unsigned int i, best_i = 0;
+       if (!pll->table[index].n)
+               return -EINVAL;
+
+       *m = pll->table[index].m;
+       *n = pll->table[index].n;
+
+       return 0;
+}
+
+static unsigned int meson_clk_get_pll_range_m(unsigned long rate,
+                                             unsigned long parent_rate,
+                                             unsigned int n,
+                                             struct meson_clk_pll_data *pll)
+{
+       u64 val = (u64)rate * n;
 
-       if (!table)
-               return NULL;
+       if (__pll_round_closest_mult(pll))
+               return DIV_ROUND_CLOSEST_ULL(val, parent_rate);
 
-       for (i = 0; table[i].n; i++) {
-               now = __pll_params_to_rate(parent_rate, &table[i], 0, pll);
+       return div_u64(val,  parent_rate);
+}
 
-               /* If we get an exact match, don't bother any further */
-               if (now == rate) {
-                       return &table[i];
-               } else if (meson_clk_pll_is_better(rate, best, now, pll)) {
+static int meson_clk_get_pll_range_index(unsigned long rate,
+                                        unsigned long parent_rate,
+                                        unsigned int index,
+                                        unsigned int *m,
+                                        unsigned int *n,
+                                        struct meson_clk_pll_data *pll)
+{
+       *n = index + 1;
+
+       /* Check the predivider range */
+       if (*n >= (1 << pll->n.width))
+               return -EINVAL;
+
+       if (*n == 1) {
+               /* Get the boundaries out the way */
+               if (rate <= pll->range->min * parent_rate) {
+                       *m = pll->range->min;
+                       return -ENODATA;
+               } else if (rate >= pll->range->max * parent_rate) {
+                       *m = pll->range->max;
+                       return -ENODATA;
+               }
+       }
+
+       *m = meson_clk_get_pll_range_m(rate, parent_rate, *n, pll);
+
+       /* the pre-divider gives a multiplier too big - stop */
+       if (*m >= (1 << pll->m.width))
+               return -EINVAL;
+
+       return 0;
+}
+
+static int meson_clk_get_pll_get_index(unsigned long rate,
+                                      unsigned long parent_rate,
+                                      unsigned int index,
+                                      unsigned int *m,
+                                      unsigned int *n,
+                                      struct meson_clk_pll_data *pll)
+{
+       if (pll->range)
+               return meson_clk_get_pll_range_index(rate, parent_rate,
+                                                    index, m, n, pll);
+       else if (pll->table)
+               return meson_clk_get_pll_table_index(index, m, n, pll);
+
+       return -EINVAL;
+}
+
+static int meson_clk_get_pll_settings(unsigned long rate,
+                                     unsigned long parent_rate,
+                                     unsigned int *best_m,
+                                     unsigned int *best_n,
+                                     struct meson_clk_pll_data *pll)
+{
+       unsigned long best = 0, now = 0;
+       unsigned int i, m, n;
+       int ret;
+
+       for (i = 0, ret = 0; !ret; i++) {
+               ret = meson_clk_get_pll_get_index(rate, parent_rate,
+                                                 i, &m, &n, pll);
+               if (ret == -EINVAL)
+                       break;
+
+               now = __pll_params_to_rate(parent_rate, m, n, 0, pll);
+               if (meson_clk_pll_is_better(rate, best, now, pll)) {
                        best = now;
-                       best_i = i;
+                       *best_m = m;
+                       *best_n = n;
+
+                       if (now == rate)
+                               break;
                }
        }
 
-       return (struct pll_params_table *)&table[best_i];
+       return best ? 0 : -EINVAL;
 }
 
 static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
@@ -148,15 +238,15 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct clk_regmap *clk = to_clk_regmap(hw);
        struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
-       const struct pll_params_table *pllt =
-               meson_clk_get_pll_settings(rate, *parent_rate, pll);
+       unsigned int m, n, frac;
        unsigned long round;
-       u16 frac;
+       int ret;
 
-       if (!pllt)
+       ret = meson_clk_get_pll_settings(rate, *parent_rate, &m, &n, pll);
+       if (ret)
                return meson_clk_pll_recalc_rate(hw, *parent_rate);
 
-       round = __pll_params_to_rate(*parent_rate, pllt, 0, pll);
+       round = __pll_params_to_rate(*parent_rate, m, n, 0, pll);
 
        if (!MESON_PARM_APPLICABLE(&pll->frac) || rate == round)
                return round;
@@ -165,9 +255,9 @@ static long meson_clk_pll_round_rate(struct clk_hw *hw, unsigned long rate,
         * The rate provided by the setting is not an exact match, let's
         * try to improve the result using the fractional parameter
         */
-       frac = __pll_params_with_frac(rate, *parent_rate, pllt, pll);
+       frac = __pll_params_with_frac(rate, *parent_rate, m, n, pll);
 
-       return __pll_params_to_rate(*parent_rate, pllt, frac, pll);
+       return __pll_params_to_rate(*parent_rate, m, n, frac, pll);
 }
 
 static int meson_clk_pll_wait_lock(struct clk_hw *hw)
@@ -254,30 +344,27 @@ static int meson_clk_pll_set_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct clk_regmap *clk = to_clk_regmap(hw);
        struct meson_clk_pll_data *pll = meson_clk_pll_data(clk);
-       const struct pll_params_table *pllt;
-       unsigned int enabled;
+       unsigned int enabled, m, n, frac = 0, ret;
        unsigned long old_rate;
-       u16 frac = 0;
 
        if (parent_rate == 0 || rate == 0)
                return -EINVAL;
 
        old_rate = rate;
 
-       pllt = meson_clk_get_pll_settings(rate, parent_rate, pll);
-       if (!pllt)
-               return -EINVAL;
+       ret = meson_clk_get_pll_settings(rate, parent_rate, &m, &n, pll);
+       if (ret)
+               return ret;
 
        enabled = meson_parm_read(clk->map, &pll->en);
        if (enabled)
                meson_clk_pll_disable(hw);
 
-       meson_parm_write(clk->map, &pll->n, pllt->n);
-       meson_parm_write(clk->map, &pll->m, pllt->m);
-
+       meson_parm_write(clk->map, &pll->n, n);
+       meson_parm_write(clk->map, &pll->m, m);
 
        if (MESON_PARM_APPLICABLE(&pll->frac)) {
-               frac = __pll_params_with_frac(rate, parent_rate, pllt, pll);
+               frac = __pll_params_with_frac(rate, parent_rate, m, n, pll);
                meson_parm_write(clk->map, &pll->frac, frac);
        }
 
@@ -309,8 +396,15 @@ const struct clk_ops meson_clk_pll_ops = {
        .enable         = meson_clk_pll_enable,
        .disable        = meson_clk_pll_disable
 };
+EXPORT_SYMBOL_GPL(meson_clk_pll_ops);
 
 const struct clk_ops meson_clk_pll_ro_ops = {
        .recalc_rate    = meson_clk_pll_recalc_rate,
        .is_enabled     = meson_clk_pll_is_enabled,
 };
+EXPORT_SYMBOL_GPL(meson_clk_pll_ro_ops);
+
+MODULE_DESCRIPTION("Amlogic PLL driver");
+MODULE_AUTHOR("Carlo Caione <carlo@endlessm.com>");
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/clk-pll.h b/drivers/clk/meson/clk-pll.h
new file mode 100644 (file)
index 0000000..55af2e2
--- /dev/null
@@ -0,0 +1,49 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+#ifndef __MESON_CLK_PLL_H
+#define __MESON_CLK_PLL_H
+
+#include <linux/clk-provider.h>
+#include <linux/regmap.h>
+#include "parm.h"
+
+struct pll_params_table {
+       unsigned int    m;
+       unsigned int    n;
+};
+
+struct pll_mult_range {
+       unsigned int    min;
+       unsigned int    max;
+};
+
+#define PLL_PARAMS(_m, _n)                                             \
+       {                                                               \
+               .m              = (_m),                                 \
+               .n              = (_n),                                 \
+       }
+
+#define CLK_MESON_PLL_ROUND_CLOSEST    BIT(0)
+
+struct meson_clk_pll_data {
+       struct parm en;
+       struct parm m;
+       struct parm n;
+       struct parm frac;
+       struct parm l;
+       struct parm rst;
+       const struct reg_sequence *init_regs;
+       unsigned int init_count;
+       const struct pll_params_table *table;
+       const struct pll_mult_range *range;
+       u8 flags;
+};
+
+extern const struct clk_ops meson_clk_pll_ro_ops;
+extern const struct clk_ops meson_clk_pll_ops;
+
+#endif /* __MESON_CLK_PLL_H */
index c515f67..dcd1757 100644 (file)
@@ -4,6 +4,7 @@
  * Author: Jerome Brunet <jbrunet@baylibre.com>
  */
 
+#include <linux/module.h>
 #include "clk-regmap.h"
 
 static int clk_regmap_gate_endisable(struct clk_hw *hw, int enable)
@@ -180,3 +181,7 @@ const struct clk_ops clk_regmap_mux_ro_ops = {
        .get_parent = clk_regmap_mux_get_parent,
 };
 EXPORT_SYMBOL_GPL(clk_regmap_mux_ro_ops);
+
+MODULE_DESCRIPTION("Amlogic regmap backed clock driver");
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
+MODULE_LICENSE("GPL v2");
index e9c5728..1dd0abe 100644 (file)
@@ -111,4 +111,24 @@ clk_get_regmap_mux_data(struct clk_regmap *clk)
 extern const struct clk_ops clk_regmap_mux_ops;
 extern const struct clk_ops clk_regmap_mux_ro_ops;
 
+#define __MESON_GATE(_name, _reg, _bit, _ops)                          \
+struct clk_regmap _name = {                                            \
+       .data = &(struct clk_regmap_gate_data){                         \
+               .offset = (_reg),                                       \
+               .bit_idx = (_bit),                                      \
+       },                                                              \
+       .hw.init = &(struct clk_init_data) {                            \
+               .name = #_name,                                         \
+               .ops = _ops,                                            \
+               .parent_names = (const char *[]){ "clk81" },            \
+               .num_parents = 1,                                       \
+               .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),     \
+       },                                                              \
+}
+
+#define MESON_GATE(_name, _reg, _bit)  \
+       __MESON_GATE(_name, _reg, _bit, &clk_regmap_gate_ops)
+
+#define MESON_GATE_RO(_name, _reg, _bit)       \
+       __MESON_GATE(_name, _reg, _bit, &clk_regmap_gate_ro_ops)
 #endif /* __CLK_REGMAP_H */
diff --git a/drivers/clk/meson/clk-triphase.c b/drivers/clk/meson/clk-triphase.c
deleted file mode 100644 (file)
index 4a59936..0000000
+++ /dev/null
@@ -1,68 +0,0 @@
-// SPDX-License-Identifier: (GPL-2.0 OR MIT)
-/*
- * Copyright (c) 2018 BayLibre, SAS.
- * Author: Jerome Brunet <jbrunet@baylibre.com>
- */
-
-#include <linux/clk-provider.h>
-#include "clkc-audio.h"
-
-/*
- * This is a special clock for the audio controller.
- * The phase of mst_sclk clock output can be controlled independently
- * for the outside world (ph0), the tdmout (ph1) and tdmin (ph2).
- * Controlling these 3 phases as just one makes things simpler and
- * give the same clock view to all the element on the i2s bus.
- * If necessary, we can still control the phase in the tdm block
- * which makes these independent control redundant.
- */
-static inline struct meson_clk_triphase_data *
-meson_clk_triphase_data(struct clk_regmap *clk)
-{
-       return (struct meson_clk_triphase_data *)clk->data;
-}
-
-static void meson_clk_triphase_sync(struct clk_hw *hw)
-{
-       struct clk_regmap *clk = to_clk_regmap(hw);
-       struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk);
-       unsigned int val;
-
-       /* Get phase 0 and sync it to phase 1 and 2 */
-       val = meson_parm_read(clk->map, &tph->ph0);
-       meson_parm_write(clk->map, &tph->ph1, val);
-       meson_parm_write(clk->map, &tph->ph2, val);
-}
-
-static int meson_clk_triphase_get_phase(struct clk_hw *hw)
-{
-       struct clk_regmap *clk = to_clk_regmap(hw);
-       struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk);
-       unsigned int val;
-
-       /* Phase are in sync, reading phase 0 is enough */
-       val = meson_parm_read(clk->map, &tph->ph0);
-
-       return meson_clk_degrees_from_val(val, tph->ph0.width);
-}
-
-static int meson_clk_triphase_set_phase(struct clk_hw *hw, int degrees)
-{
-       struct clk_regmap *clk = to_clk_regmap(hw);
-       struct meson_clk_triphase_data *tph = meson_clk_triphase_data(clk);
-       unsigned int val;
-
-       val = meson_clk_degrees_to_val(degrees, tph->ph0.width);
-       meson_parm_write(clk->map, &tph->ph0, val);
-       meson_parm_write(clk->map, &tph->ph1, val);
-       meson_parm_write(clk->map, &tph->ph2, val);
-
-       return 0;
-}
-
-const struct clk_ops meson_clk_triphase_ops = {
-       .init           = meson_clk_triphase_sync,
-       .get_phase      = meson_clk_triphase_get_phase,
-       .set_phase      = meson_clk_triphase_set_phase,
-};
-EXPORT_SYMBOL_GPL(meson_clk_triphase_ops);
diff --git a/drivers/clk/meson/clkc-audio.h b/drivers/clk/meson/clkc-audio.h
deleted file mode 100644 (file)
index 0a7c157..0000000
+++ /dev/null
@@ -1,28 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) 2018 BayLibre, SAS.
- * Author: Jerome Brunet <jbrunet@baylibre.com>
- */
-
-#ifndef __MESON_CLKC_AUDIO_H
-#define __MESON_CLKC_AUDIO_H
-
-#include "clkc.h"
-
-struct meson_clk_triphase_data {
-       struct parm ph0;
-       struct parm ph1;
-       struct parm ph2;
-};
-
-struct meson_sclk_div_data {
-       struct parm div;
-       struct parm hi;
-       unsigned int cached_div;
-       struct clk_duty cached_duty;
-};
-
-extern const struct clk_ops meson_clk_triphase_ops;
-extern const struct clk_ops meson_sclk_div_ops;
-
-#endif /* __MESON_CLKC_AUDIO_H */
diff --git a/drivers/clk/meson/clkc.h b/drivers/clk/meson/clkc.h
deleted file mode 100644 (file)
index 6183b22..0000000
+++ /dev/null
@@ -1,127 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 */
-/*
- * Copyright (c) 2015 Endless Mobile, Inc.
- * Author: Carlo Caione <carlo@endlessm.com>
- */
-
-#ifndef __CLKC_H
-#define __CLKC_H
-
-#include <linux/clk-provider.h>
-#include "clk-regmap.h"
-
-#define PMASK(width)                   GENMASK(width - 1, 0)
-#define SETPMASK(width, shift)         GENMASK(shift + width - 1, shift)
-#define CLRPMASK(width, shift)         (~SETPMASK(width, shift))
-
-#define PARM_GET(width, shift, reg)                                    \
-       (((reg) & SETPMASK(width, shift)) >> (shift))
-#define PARM_SET(width, shift, reg, val)                               \
-       (((reg) & CLRPMASK(width, shift)) | ((val) << (shift)))
-
-#define MESON_PARM_APPLICABLE(p)               (!!((p)->width))
-
-struct parm {
-       u16     reg_off;
-       u8      shift;
-       u8      width;
-};
-
-static inline unsigned int meson_parm_read(struct regmap *map, struct parm *p)
-{
-       unsigned int val;
-
-       regmap_read(map, p->reg_off, &val);
-       return PARM_GET(p->width, p->shift, val);
-}
-
-static inline void meson_parm_write(struct regmap *map, struct parm *p,
-                                   unsigned int val)
-{
-       regmap_update_bits(map, p->reg_off, SETPMASK(p->width, p->shift),
-                          val << p->shift);
-}
-
-
-struct pll_params_table {
-       u16             m;
-       u16             n;
-};
-
-#define PLL_PARAMS(_m, _n)                                             \
-       {                                                               \
-               .m              = (_m),                                 \
-               .n              = (_n),                                 \
-       }
-
-#define CLK_MESON_PLL_ROUND_CLOSEST    BIT(0)
-
-struct meson_clk_pll_data {
-       struct parm en;
-       struct parm m;
-       struct parm n;
-       struct parm frac;
-       struct parm l;
-       struct parm rst;
-       const struct reg_sequence *init_regs;
-       unsigned int init_count;
-       const struct pll_params_table *table;
-       u8 flags;
-};
-
-#define to_meson_clk_pll(_hw) container_of(_hw, struct meson_clk_pll, hw)
-
-struct meson_clk_mpll_data {
-       struct parm sdm;
-       struct parm sdm_en;
-       struct parm n2;
-       struct parm ssen;
-       struct parm misc;
-       spinlock_t *lock;
-       u8 flags;
-};
-
-#define CLK_MESON_MPLL_ROUND_CLOSEST   BIT(0)
-
-struct meson_clk_phase_data {
-       struct parm ph;
-};
-
-int meson_clk_degrees_from_val(unsigned int val, unsigned int width);
-unsigned int meson_clk_degrees_to_val(int degrees, unsigned int width);
-
-struct meson_vid_pll_div_data {
-       struct parm val;
-       struct parm sel;
-};
-
-#define MESON_GATE(_name, _reg, _bit)                                  \
-struct clk_regmap _name = {                                            \
-       .data = &(struct clk_regmap_gate_data){                         \
-               .offset = (_reg),                                       \
-               .bit_idx = (_bit),                                      \
-       },                                                              \
-       .hw.init = &(struct clk_init_data) {                            \
-               .name = #_name,                                         \
-               .ops = &clk_regmap_gate_ops,                            \
-               .parent_names = (const char *[]){ "clk81" },            \
-               .num_parents = 1,                                       \
-               .flags = (CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED),     \
-       },                                                              \
-};
-
-/* clk_ops */
-extern const struct clk_ops meson_clk_pll_ro_ops;
-extern const struct clk_ops meson_clk_pll_ops;
-extern const struct clk_ops meson_clk_cpu_ops;
-extern const struct clk_ops meson_clk_mpll_ro_ops;
-extern const struct clk_ops meson_clk_mpll_ops;
-extern const struct clk_ops meson_clk_phase_ops;
-extern const struct clk_ops meson_vid_pll_div_ro_ops;
-
-struct clk_hw *meson_clk_hw_register_input(struct device *dev,
-                                          const char *of_name,
-                                          const char *clk_name,
-                                          unsigned long flags);
-
-#endif /* __CLKC_H */
diff --git a/drivers/clk/meson/g12a-aoclk.c b/drivers/clk/meson/g12a-aoclk.c
new file mode 100644 (file)
index 0000000..1994e73
--- /dev/null
@@ -0,0 +1,454 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Amlogic Meson-AXG Clock Controller Driver
+ *
+ * Copyright (c) 2016 Baylibre SAS.
+ * Author: Michael Turquette <mturquette@baylibre.com>
+ *
+ * Copyright (c) 2019 Baylibre SAS.
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+#include <linux/clk-provider.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/mfd/syscon.h>
+#include "meson-aoclk.h"
+#include "g12a-aoclk.h"
+
+#include "clk-regmap.h"
+#include "clk-dualdiv.h"
+
+#define IN_PREFIX "ao-in-"
+
+/*
+ * AO Configuration Clock registers offsets
+ * Register offsets from the data sheet must be multiplied by 4.
+ */
+#define AO_RTI_STATUS_REG3     0x0C
+#define AO_RTI_PWR_CNTL_REG0   0x10
+#define AO_RTI_GEN_CNTL_REG0   0x40
+#define AO_CLK_GATE0           0x4c
+#define AO_CLK_GATE0_SP                0x50
+#define AO_OSCIN_CNTL          0x58
+#define AO_CEC_CLK_CNTL_REG0   0x74
+#define AO_CEC_CLK_CNTL_REG1   0x78
+#define AO_SAR_CLK             0x90
+#define AO_RTC_ALT_CLK_CNTL0   0x94
+#define AO_RTC_ALT_CLK_CNTL1   0x98
+
+/*
+ * Like every other peripheral clock gate in Amlogic Clock drivers,
+ * we are using CLK_IGNORE_UNUSED here, so we keep the state of the
+ * bootloader. The goal is to remove this flag at some point.
+ * Actually removing it will require some extensive test to be done safely.
+ */
+#define AXG_AO_GATE(_name, _reg, _bit)                                 \
+static struct clk_regmap g12a_aoclk_##_name = {                                \
+       .data = &(struct clk_regmap_gate_data) {                        \
+               .offset = (_reg),                                       \
+               .bit_idx = (_bit),                                      \
+       },                                                              \
+       .hw.init = &(struct clk_init_data) {                            \
+               .name =  "g12a_ao_" #_name,                             \
+               .ops = &clk_regmap_gate_ops,                            \
+               .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \
+               .num_parents = 1,                                       \
+               .flags = CLK_IGNORE_UNUSED,                             \
+       },                                                              \
+}
+
+AXG_AO_GATE(ahb, AO_CLK_GATE0, 0);
+AXG_AO_GATE(ir_in, AO_CLK_GATE0, 1);
+AXG_AO_GATE(i2c_m0, AO_CLK_GATE0, 2);
+AXG_AO_GATE(i2c_s0, AO_CLK_GATE0, 3);
+AXG_AO_GATE(uart, AO_CLK_GATE0, 4);
+AXG_AO_GATE(prod_i2c, AO_CLK_GATE0, 5);
+AXG_AO_GATE(uart2, AO_CLK_GATE0, 6);
+AXG_AO_GATE(ir_out, AO_CLK_GATE0, 7);
+AXG_AO_GATE(saradc, AO_CLK_GATE0, 8);
+AXG_AO_GATE(mailbox, AO_CLK_GATE0_SP, 0);
+AXG_AO_GATE(m3, AO_CLK_GATE0_SP, 1);
+AXG_AO_GATE(ahb_sram, AO_CLK_GATE0_SP, 2);
+AXG_AO_GATE(rti, AO_CLK_GATE0_SP, 3);
+AXG_AO_GATE(m4_fclk, AO_CLK_GATE0_SP, 4);
+AXG_AO_GATE(m4_hclk, AO_CLK_GATE0_SP, 5);
+
+static struct clk_regmap g12a_aoclk_cts_oscin = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = AO_RTI_PWR_CNTL_REG0,
+               .bit_idx = 14,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cts_oscin",
+               .ops = &clk_regmap_gate_ro_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+               .num_parents = 1,
+       },
+};
+
+static const struct meson_clk_dualdiv_param g12a_32k_div_table[] = {
+       {
+               .dual   = 1,
+               .n1     = 733,
+               .m1     = 8,
+               .n2     = 732,
+               .m2     = 11,
+       }, {}
+};
+
+/* 32k_by_oscin clock */
+
+static struct clk_regmap g12a_aoclk_32k_by_oscin_pre = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = AO_RTC_ALT_CLK_CNTL0,
+               .bit_idx = 31,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "g12a_ao_32k_by_oscin_pre",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "cts_oscin" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_aoclk_32k_by_oscin_div = {
+       .data = &(struct meson_clk_dualdiv_data){
+               .n1 = {
+                       .reg_off = AO_RTC_ALT_CLK_CNTL0,
+                       .shift   = 0,
+                       .width   = 12,
+               },
+               .n2 = {
+                       .reg_off = AO_RTC_ALT_CLK_CNTL0,
+                       .shift   = 12,
+                       .width   = 12,
+               },
+               .m1 = {
+                       .reg_off = AO_RTC_ALT_CLK_CNTL1,
+                       .shift   = 0,
+                       .width   = 12,
+               },
+               .m2 = {
+                       .reg_off = AO_RTC_ALT_CLK_CNTL1,
+                       .shift   = 12,
+                       .width   = 12,
+               },
+               .dual = {
+                       .reg_off = AO_RTC_ALT_CLK_CNTL0,
+                       .shift   = 28,
+                       .width   = 1,
+               },
+               .table = g12a_32k_div_table,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "g12a_ao_32k_by_oscin_div",
+               .ops = &meson_clk_dualdiv_ops,
+               .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_pre" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_aoclk_32k_by_oscin_sel = {
+       .data = &(struct clk_regmap_mux_data) {
+               .offset = AO_RTC_ALT_CLK_CNTL1,
+               .mask = 0x1,
+               .shift = 24,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "g12a_ao_32k_by_oscin_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_div",
+                                                 "g12a_ao_32k_by_oscin_pre" },
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_aoclk_32k_by_oscin = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = AO_RTC_ALT_CLK_CNTL0,
+               .bit_idx = 30,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "g12a_ao_32k_by_oscin",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+/* cec clock */
+
+static struct clk_regmap g12a_aoclk_cec_pre = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = AO_CEC_CLK_CNTL_REG0,
+               .bit_idx = 31,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "g12a_ao_cec_pre",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "cts_oscin" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_aoclk_cec_div = {
+       .data = &(struct meson_clk_dualdiv_data){
+               .n1 = {
+                       .reg_off = AO_CEC_CLK_CNTL_REG0,
+                       .shift   = 0,
+                       .width   = 12,
+               },
+               .n2 = {
+                       .reg_off = AO_CEC_CLK_CNTL_REG0,
+                       .shift   = 12,
+                       .width   = 12,
+               },
+               .m1 = {
+                       .reg_off = AO_CEC_CLK_CNTL_REG1,
+                       .shift   = 0,
+                       .width   = 12,
+               },
+               .m2 = {
+                       .reg_off = AO_CEC_CLK_CNTL_REG1,
+                       .shift   = 12,
+                       .width   = 12,
+               },
+               .dual = {
+                       .reg_off = AO_CEC_CLK_CNTL_REG0,
+                       .shift   = 28,
+                       .width   = 1,
+               },
+               .table = g12a_32k_div_table,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "g12a_ao_cec_div",
+               .ops = &meson_clk_dualdiv_ops,
+               .parent_names = (const char *[]){ "g12a_ao_cec_pre" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_aoclk_cec_sel = {
+       .data = &(struct clk_regmap_mux_data) {
+               .offset = AO_CEC_CLK_CNTL_REG1,
+               .mask = 0x1,
+               .shift = 24,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "g12a_ao_cec_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = (const char *[]){ "g12a_ao_cec_div",
+                                                 "g12a_ao_cec_pre" },
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_aoclk_cec = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = AO_CEC_CLK_CNTL_REG0,
+               .bit_idx = 30,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "g12a_ao_cec",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "g12a_ao_cec_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_aoclk_cts_rtc_oscin = {
+       .data = &(struct clk_regmap_mux_data) {
+               .offset = AO_RTI_PWR_CNTL_REG0,
+               .mask = 0x1,
+               .shift = 10,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "g12a_ao_cts_rtc_oscin",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = (const char *[]){ "g12a_ao_32k_by_oscin",
+                                                 IN_PREFIX "ext_32k-0" },
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_aoclk_clk81 = {
+       .data = &(struct clk_regmap_mux_data) {
+               .offset = AO_RTI_PWR_CNTL_REG0,
+               .mask = 0x1,
+               .shift = 8,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "g12a_ao_clk81",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk",
+                                                 "g12a_ao_cts_rtc_oscin"},
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_aoclk_saradc_mux = {
+       .data = &(struct clk_regmap_mux_data) {
+               .offset = AO_SAR_CLK,
+               .mask = 0x3,
+               .shift = 9,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "g12a_ao_saradc_mux",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "xtal",
+                                                 "g12a_ao_clk81" },
+               .num_parents = 2,
+       },
+};
+
+static struct clk_regmap g12a_aoclk_saradc_div = {
+       .data = &(struct clk_regmap_div_data) {
+               .offset = AO_SAR_CLK,
+               .shift = 0,
+               .width = 8,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "g12a_ao_saradc_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "g12a_ao_saradc_mux" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_aoclk_saradc_gate = {
+       .data = &(struct clk_regmap_gate_data) {
+               .offset = AO_SAR_CLK,
+               .bit_idx = 8,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "g12a_ao_saradc_gate",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "g12a_ao_saradc_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static const unsigned int g12a_aoclk_reset[] = {
+       [RESET_AO_IR_IN]        = 16,
+       [RESET_AO_UART]         = 17,
+       [RESET_AO_I2C_M]        = 18,
+       [RESET_AO_I2C_S]        = 19,
+       [RESET_AO_SAR_ADC]      = 20,
+       [RESET_AO_UART2]        = 22,
+       [RESET_AO_IR_OUT]       = 23,
+};
+
+static struct clk_regmap *g12a_aoclk_regmap[] = {
+       &g12a_aoclk_ahb,
+       &g12a_aoclk_ir_in,
+       &g12a_aoclk_i2c_m0,
+       &g12a_aoclk_i2c_s0,
+       &g12a_aoclk_uart,
+       &g12a_aoclk_prod_i2c,
+       &g12a_aoclk_uart2,
+       &g12a_aoclk_ir_out,
+       &g12a_aoclk_saradc,
+       &g12a_aoclk_mailbox,
+       &g12a_aoclk_m3,
+       &g12a_aoclk_ahb_sram,
+       &g12a_aoclk_rti,
+       &g12a_aoclk_m4_fclk,
+       &g12a_aoclk_m4_hclk,
+       &g12a_aoclk_cts_oscin,
+       &g12a_aoclk_32k_by_oscin_pre,
+       &g12a_aoclk_32k_by_oscin_div,
+       &g12a_aoclk_32k_by_oscin_sel,
+       &g12a_aoclk_32k_by_oscin,
+       &g12a_aoclk_cec_pre,
+       &g12a_aoclk_cec_div,
+       &g12a_aoclk_cec_sel,
+       &g12a_aoclk_cec,
+       &g12a_aoclk_cts_rtc_oscin,
+       &g12a_aoclk_clk81,
+       &g12a_aoclk_saradc_mux,
+       &g12a_aoclk_saradc_div,
+       &g12a_aoclk_saradc_gate,
+};
+
+static const struct clk_hw_onecell_data g12a_aoclk_onecell_data = {
+       .hws = {
+               [CLKID_AO_AHB]          = &g12a_aoclk_ahb.hw,
+               [CLKID_AO_IR_IN]        = &g12a_aoclk_ir_in.hw,
+               [CLKID_AO_I2C_M0]       = &g12a_aoclk_i2c_m0.hw,
+               [CLKID_AO_I2C_S0]       = &g12a_aoclk_i2c_s0.hw,
+               [CLKID_AO_UART]         = &g12a_aoclk_uart.hw,
+               [CLKID_AO_PROD_I2C]     = &g12a_aoclk_prod_i2c.hw,
+               [CLKID_AO_UART2]        = &g12a_aoclk_uart2.hw,
+               [CLKID_AO_IR_OUT]       = &g12a_aoclk_ir_out.hw,
+               [CLKID_AO_SAR_ADC]      = &g12a_aoclk_saradc.hw,
+               [CLKID_AO_MAILBOX]      = &g12a_aoclk_mailbox.hw,
+               [CLKID_AO_M3]           = &g12a_aoclk_m3.hw,
+               [CLKID_AO_AHB_SRAM]     = &g12a_aoclk_ahb_sram.hw,
+               [CLKID_AO_RTI]          = &g12a_aoclk_rti.hw,
+               [CLKID_AO_M4_FCLK]      = &g12a_aoclk_m4_fclk.hw,
+               [CLKID_AO_M4_HCLK]      = &g12a_aoclk_m4_hclk.hw,
+               [CLKID_AO_CLK81]        = &g12a_aoclk_clk81.hw,
+               [CLKID_AO_SAR_ADC_SEL]  = &g12a_aoclk_saradc_mux.hw,
+               [CLKID_AO_SAR_ADC_DIV]  = &g12a_aoclk_saradc_div.hw,
+               [CLKID_AO_SAR_ADC_CLK]  = &g12a_aoclk_saradc_gate.hw,
+               [CLKID_AO_CTS_OSCIN]    = &g12a_aoclk_cts_oscin.hw,
+               [CLKID_AO_32K_PRE]      = &g12a_aoclk_32k_by_oscin_pre.hw,
+               [CLKID_AO_32K_DIV]      = &g12a_aoclk_32k_by_oscin_div.hw,
+               [CLKID_AO_32K_SEL]      = &g12a_aoclk_32k_by_oscin_sel.hw,
+               [CLKID_AO_32K]          = &g12a_aoclk_32k_by_oscin.hw,
+               [CLKID_AO_CEC_PRE]      = &g12a_aoclk_cec_pre.hw,
+               [CLKID_AO_CEC_DIV]      = &g12a_aoclk_cec_div.hw,
+               [CLKID_AO_CEC_SEL]      = &g12a_aoclk_cec_sel.hw,
+               [CLKID_AO_CEC]          = &g12a_aoclk_cec.hw,
+               [CLKID_AO_CTS_RTC_OSCIN] = &g12a_aoclk_cts_rtc_oscin.hw,
+       },
+       .num = NR_CLKS,
+};
+
+static const struct meson_aoclk_input g12a_aoclk_inputs[] = {
+       { .name = "xtal",       .required = true  },
+       { .name = "mpeg-clk",   .required = true  },
+       { .name = "ext-32k-0",  .required = false },
+};
+
+static const struct meson_aoclk_data g12a_aoclkc_data = {
+       .reset_reg      = AO_RTI_GEN_CNTL_REG0,
+       .num_reset      = ARRAY_SIZE(g12a_aoclk_reset),
+       .reset          = g12a_aoclk_reset,
+       .num_clks       = ARRAY_SIZE(g12a_aoclk_regmap),
+       .clks           = g12a_aoclk_regmap,
+       .hw_data        = &g12a_aoclk_onecell_data,
+       .inputs         = g12a_aoclk_inputs,
+       .num_inputs     = ARRAY_SIZE(g12a_aoclk_inputs),
+       .input_prefix   = IN_PREFIX,
+};
+
+static const struct of_device_id g12a_aoclkc_match_table[] = {
+       {
+               .compatible     = "amlogic,meson-g12a-aoclkc",
+               .data           = &g12a_aoclkc_data,
+       },
+       { }
+};
+
+static struct platform_driver g12a_aoclkc_driver = {
+       .probe          = meson_aoclkc_probe,
+       .driver         = {
+               .name   = "g12a-aoclkc",
+               .of_match_table = g12a_aoclkc_match_table,
+       },
+};
+
+builtin_platform_driver(g12a_aoclkc_driver);
diff --git a/drivers/clk/meson/g12a-aoclk.h b/drivers/clk/meson/g12a-aoclk.h
new file mode 100644 (file)
index 0000000..04b0d55
--- /dev/null
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2019 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#ifndef __G12A_AOCLKC_H
+#define __G12A_AOCLKC_H
+
+/*
+ * CLKID index values
+ *
+ * These indices are entirely contrived and do not map onto the hardware.
+ * It has now been decided to expose everything by default in the DT header:
+ * include/dt-bindings/clock/g12a-aoclkc.h. Only the clocks ids we don't want
+ * to expose, such as the internal muxes and dividers of composite clocks,
+ * will remain defined here.
+ */
+#define CLKID_AO_SAR_ADC_SEL   16
+#define CLKID_AO_SAR_ADC_DIV   17
+#define CLKID_AO_CTS_OSCIN     19
+#define CLKID_AO_32K_PRE       20
+#define CLKID_AO_32K_DIV       21
+#define CLKID_AO_32K_SEL       22
+#define CLKID_AO_CEC_PRE       24
+#define CLKID_AO_CEC_DIV       25
+#define CLKID_AO_CEC_SEL       26
+
+#define NR_CLKS        29
+
+#include <dt-bindings/clock/g12a-aoclkc.h>
+#include <dt-bindings/reset/g12a-aoclkc.h>
+
+#endif /* __G12A_AOCLKC_H */
diff --git a/drivers/clk/meson/g12a.c b/drivers/clk/meson/g12a.c
new file mode 100644 (file)
index 0000000..0e1ce8c
--- /dev/null
@@ -0,0 +1,2359 @@
+// SPDX-License-Identifier: GPL-2.0+
+/*
+ * Amlogic Meson-G12A Clock Controller Driver
+ *
+ * Copyright (c) 2016 Baylibre SAS.
+ * Author: Michael Turquette <mturquette@baylibre.com>
+ *
+ * Copyright (c) 2018 Amlogic, inc.
+ * Author: Qiufang Dai <qiufang.dai@amlogic.com>
+ * Author: Jian Hu <jian.hu@amlogic.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/init.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+
+#include "clk-input.h"
+#include "clk-mpll.h"
+#include "clk-pll.h"
+#include "clk-regmap.h"
+#include "vid-pll-div.h"
+#include "meson-eeclk.h"
+#include "g12a.h"
+
+static DEFINE_SPINLOCK(meson_clk_lock);
+
+static struct clk_regmap g12a_fixed_pll_dco = {
+       .data = &(struct meson_clk_pll_data){
+               .en = {
+                       .reg_off = HHI_FIX_PLL_CNTL0,
+                       .shift   = 28,
+                       .width   = 1,
+               },
+               .m = {
+                       .reg_off = HHI_FIX_PLL_CNTL0,
+                       .shift   = 0,
+                       .width   = 8,
+               },
+               .n = {
+                       .reg_off = HHI_FIX_PLL_CNTL0,
+                       .shift   = 10,
+                       .width   = 5,
+               },
+               .frac = {
+                       .reg_off = HHI_FIX_PLL_CNTL1,
+                       .shift   = 0,
+                       .width   = 17,
+               },
+               .l = {
+                       .reg_off = HHI_FIX_PLL_CNTL0,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_FIX_PLL_CNTL0,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fixed_pll_dco",
+               .ops = &meson_clk_pll_ro_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_fixed_pll = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_FIX_PLL_CNTL0,
+               .shift = 16,
+               .width = 2,
+               .flags = CLK_DIVIDER_POWER_OF_TWO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fixed_pll",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "fixed_pll_dco" },
+               .num_parents = 1,
+               /*
+                * This clock won't ever change at runtime so
+                * CLK_SET_RATE_PARENT is not required
+                */
+       },
+};
+
+/*
+ * Internal sys pll emulation configuration parameters
+ */
+static const struct reg_sequence g12a_sys_init_regs[] = {
+       { .reg = HHI_SYS_PLL_CNTL1,     .def = 0x00000000 },
+       { .reg = HHI_SYS_PLL_CNTL2,     .def = 0x00000000 },
+       { .reg = HHI_SYS_PLL_CNTL3,     .def = 0x48681c00 },
+       { .reg = HHI_SYS_PLL_CNTL4,     .def = 0x88770290 },
+       { .reg = HHI_SYS_PLL_CNTL5,     .def = 0x39272000 },
+       { .reg = HHI_SYS_PLL_CNTL6,     .def = 0x56540000 },
+};
+
+static struct clk_regmap g12a_sys_pll_dco = {
+       .data = &(struct meson_clk_pll_data){
+               .en = {
+                       .reg_off = HHI_SYS_PLL_CNTL0,
+                       .shift   = 28,
+                       .width   = 1,
+               },
+               .m = {
+                       .reg_off = HHI_SYS_PLL_CNTL0,
+                       .shift   = 0,
+                       .width   = 8,
+               },
+               .n = {
+                       .reg_off = HHI_SYS_PLL_CNTL0,
+                       .shift   = 10,
+                       .width   = 5,
+               },
+               .l = {
+                       .reg_off = HHI_SYS_PLL_CNTL0,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_SYS_PLL_CNTL0,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+               .init_regs = g12a_sys_init_regs,
+               .init_count = ARRAY_SIZE(g12a_sys_init_regs),
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "sys_pll_dco",
+               .ops = &meson_clk_pll_ro_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_sys_pll = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SYS_PLL_CNTL0,
+               .shift = 16,
+               .width = 3,
+               .flags = CLK_DIVIDER_POWER_OF_TWO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "sys_pll",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "sys_pll_dco" },
+               .num_parents = 1,
+       },
+};
+
+static const struct pll_mult_range g12a_gp0_pll_mult_range = {
+       .min = 55,
+       .max = 255,
+};
+
+/*
+ * Internal gp0 pll emulation configuration parameters
+ */
+static const struct reg_sequence g12a_gp0_init_regs[] = {
+       { .reg = HHI_GP0_PLL_CNTL1,     .def = 0x00000000 },
+       { .reg = HHI_GP0_PLL_CNTL2,     .def = 0x00000000 },
+       { .reg = HHI_GP0_PLL_CNTL3,     .def = 0x48681c00 },
+       { .reg = HHI_GP0_PLL_CNTL4,     .def = 0x33771290 },
+       { .reg = HHI_GP0_PLL_CNTL5,     .def = 0x39272000 },
+       { .reg = HHI_GP0_PLL_CNTL6,     .def = 0x56540000 },
+};
+
+static struct clk_regmap g12a_gp0_pll_dco = {
+       .data = &(struct meson_clk_pll_data){
+               .en = {
+                       .reg_off = HHI_GP0_PLL_CNTL0,
+                       .shift   = 28,
+                       .width   = 1,
+               },
+               .m = {
+                       .reg_off = HHI_GP0_PLL_CNTL0,
+                       .shift   = 0,
+                       .width   = 8,
+               },
+               .n = {
+                       .reg_off = HHI_GP0_PLL_CNTL0,
+                       .shift   = 10,
+                       .width   = 5,
+               },
+               .frac = {
+                       .reg_off = HHI_GP0_PLL_CNTL1,
+                       .shift   = 0,
+                       .width   = 17,
+               },
+               .l = {
+                       .reg_off = HHI_GP0_PLL_CNTL0,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_GP0_PLL_CNTL0,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+               .range = &g12a_gp0_pll_mult_range,
+               .init_regs = g12a_gp0_init_regs,
+               .init_count = ARRAY_SIZE(g12a_gp0_init_regs),
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "gp0_pll_dco",
+               .ops = &meson_clk_pll_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_gp0_pll = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_GP0_PLL_CNTL0,
+               .shift = 16,
+               .width = 3,
+               .flags = (CLK_DIVIDER_POWER_OF_TWO |
+                         CLK_DIVIDER_ROUND_CLOSEST),
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "gp0_pll",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "gp0_pll_dco" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+/*
+ * Internal hifi pll emulation configuration parameters
+ */
+static const struct reg_sequence g12a_hifi_init_regs[] = {
+       { .reg = HHI_HIFI_PLL_CNTL1,    .def = 0x00000000 },
+       { .reg = HHI_HIFI_PLL_CNTL2,    .def = 0x00000000 },
+       { .reg = HHI_HIFI_PLL_CNTL3,    .def = 0x6a285c00 },
+       { .reg = HHI_HIFI_PLL_CNTL4,    .def = 0x65771290 },
+       { .reg = HHI_HIFI_PLL_CNTL5,    .def = 0x39272000 },
+       { .reg = HHI_HIFI_PLL_CNTL6,    .def = 0x56540000 },
+};
+
+static struct clk_regmap g12a_hifi_pll_dco = {
+       .data = &(struct meson_clk_pll_data){
+               .en = {
+                       .reg_off = HHI_HIFI_PLL_CNTL0,
+                       .shift   = 28,
+                       .width   = 1,
+               },
+               .m = {
+                       .reg_off = HHI_HIFI_PLL_CNTL0,
+                       .shift   = 0,
+                       .width   = 8,
+               },
+               .n = {
+                       .reg_off = HHI_HIFI_PLL_CNTL0,
+                       .shift   = 10,
+                       .width   = 5,
+               },
+               .frac = {
+                       .reg_off = HHI_HIFI_PLL_CNTL1,
+                       .shift   = 0,
+                       .width   = 17,
+               },
+               .l = {
+                       .reg_off = HHI_HIFI_PLL_CNTL0,
+                       .shift   = 31,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_HIFI_PLL_CNTL0,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+               .range = &g12a_gp0_pll_mult_range,
+               .init_regs = g12a_hifi_init_regs,
+               .init_count = ARRAY_SIZE(g12a_hifi_init_regs),
+               .flags = CLK_MESON_PLL_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "hifi_pll_dco",
+               .ops = &meson_clk_pll_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_hifi_pll = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_HIFI_PLL_CNTL0,
+               .shift = 16,
+               .width = 2,
+               .flags = (CLK_DIVIDER_POWER_OF_TWO |
+                         CLK_DIVIDER_ROUND_CLOSEST),
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "hifi_pll",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "hifi_pll_dco" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_hdmi_pll_dco = {
+       .data = &(struct meson_clk_pll_data){
+               .en = {
+                       .reg_off = HHI_HDMI_PLL_CNTL0,
+                       .shift   = 28,
+                       .width   = 1,
+               },
+               .m = {
+                       .reg_off = HHI_HDMI_PLL_CNTL0,
+                       .shift   = 0,
+                       .width   = 8,
+               },
+               .n = {
+                       .reg_off = HHI_HDMI_PLL_CNTL0,
+                       .shift   = 10,
+                       .width   = 5,
+               },
+               .frac = {
+                       .reg_off = HHI_HDMI_PLL_CNTL1,
+                       .shift   = 0,
+                       .width   = 16,
+               },
+               .l = {
+                       .reg_off = HHI_HDMI_PLL_CNTL0,
+                       .shift   = 30,
+                       .width   = 1,
+               },
+               .rst = {
+                       .reg_off = HHI_HDMI_PLL_CNTL0,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "hdmi_pll_dco",
+               .ops = &meson_clk_pll_ro_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+               .num_parents = 1,
+               /*
+                * Display directly handle hdmi pll registers ATM, we need
+                * NOCACHE to keep our view of the clock as accurate as possible
+                */
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap g12a_hdmi_pll_od = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_HDMI_PLL_CNTL0,
+               .shift = 16,
+               .width = 2,
+               .flags = CLK_DIVIDER_POWER_OF_TWO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "hdmi_pll_od",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "hdmi_pll_dco" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_hdmi_pll_od2 = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_HDMI_PLL_CNTL0,
+               .shift = 18,
+               .width = 2,
+               .flags = CLK_DIVIDER_POWER_OF_TWO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "hdmi_pll_od2",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "hdmi_pll_od" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_hdmi_pll = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_HDMI_PLL_CNTL0,
+               .shift = 20,
+               .width = 2,
+               .flags = CLK_DIVIDER_POWER_OF_TWO,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "hdmi_pll",
+               .ops = &clk_regmap_divider_ro_ops,
+               .parent_names = (const char *[]){ "hdmi_pll_od2" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE | CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_fixed_factor g12a_fclk_div2_div = {
+       .mult = 1,
+       .div = 2,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div2_div",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_fclk_div2 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_FIX_PLL_CNTL1,
+               .bit_idx = 24,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div2",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div2_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor g12a_fclk_div3_div = {
+       .mult = 1,
+       .div = 3,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div3_div",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_fclk_div3 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_FIX_PLL_CNTL1,
+               .bit_idx = 20,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div3",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div3_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor g12a_fclk_div4_div = {
+       .mult = 1,
+       .div = 4,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div4_div",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_fclk_div4 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_FIX_PLL_CNTL1,
+               .bit_idx = 21,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div4",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div4_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor g12a_fclk_div5_div = {
+       .mult = 1,
+       .div = 5,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div5_div",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_fclk_div5 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_FIX_PLL_CNTL1,
+               .bit_idx = 22,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div5",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div5_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor g12a_fclk_div7_div = {
+       .mult = 1,
+       .div = 7,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div7_div",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_fclk_div7 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_FIX_PLL_CNTL1,
+               .bit_idx = 23,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div7",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div7_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor g12a_fclk_div2p5_div = {
+       .mult = 1,
+       .div = 5,
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div2p5_div",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll_dco" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_fclk_div2p5 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_FIX_PLL_CNTL1,
+               .bit_idx = 25,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "fclk_div2p5",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "fclk_div2p5_div" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor g12a_mpll_50m_div = {
+       .mult = 1,
+       .div = 80,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll_50m_div",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll_dco" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_mpll_50m = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_FIX_PLL_CNTL3,
+               .mask = 0x1,
+               .shift = 5,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll_50m",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "xtal",
+                                                 "mpll_50m_div" },
+               .num_parents = 2,
+       },
+};
+
+static struct clk_fixed_factor g12a_mpll_prediv = {
+       .mult = 1,
+       .div = 2,
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll_prediv",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "fixed_pll_dco" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_mpll0_div = {
+       .data = &(struct meson_clk_mpll_data){
+               .sdm = {
+                       .reg_off = HHI_MPLL_CNTL1,
+                       .shift   = 0,
+                       .width   = 14,
+               },
+               .sdm_en = {
+                       .reg_off = HHI_MPLL_CNTL1,
+                       .shift   = 30,
+                       .width   = 1,
+               },
+               .n2 = {
+                       .reg_off = HHI_MPLL_CNTL1,
+                       .shift   = 20,
+                       .width   = 9,
+               },
+               .ssen = {
+                       .reg_off = HHI_MPLL_CNTL1,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+               .lock = &meson_clk_lock,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll0_div",
+               .ops = &meson_clk_mpll_ops,
+               .parent_names = (const char *[]){ "mpll_prediv" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_mpll0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL1,
+               .bit_idx = 31,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll0",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mpll0_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_mpll1_div = {
+       .data = &(struct meson_clk_mpll_data){
+               .sdm = {
+                       .reg_off = HHI_MPLL_CNTL3,
+                       .shift   = 0,
+                       .width   = 14,
+               },
+               .sdm_en = {
+                       .reg_off = HHI_MPLL_CNTL3,
+                       .shift   = 30,
+                       .width   = 1,
+               },
+               .n2 = {
+                       .reg_off = HHI_MPLL_CNTL3,
+                       .shift   = 20,
+                       .width   = 9,
+               },
+               .ssen = {
+                       .reg_off = HHI_MPLL_CNTL3,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+               .lock = &meson_clk_lock,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll1_div",
+               .ops = &meson_clk_mpll_ops,
+               .parent_names = (const char *[]){ "mpll_prediv" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_mpll1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL3,
+               .bit_idx = 31,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mpll1_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_mpll2_div = {
+       .data = &(struct meson_clk_mpll_data){
+               .sdm = {
+                       .reg_off = HHI_MPLL_CNTL5,
+                       .shift   = 0,
+                       .width   = 14,
+               },
+               .sdm_en = {
+                       .reg_off = HHI_MPLL_CNTL5,
+                       .shift   = 30,
+                       .width   = 1,
+               },
+               .n2 = {
+                       .reg_off = HHI_MPLL_CNTL5,
+                       .shift   = 20,
+                       .width   = 9,
+               },
+               .ssen = {
+                       .reg_off = HHI_MPLL_CNTL5,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+               .lock = &meson_clk_lock,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll2_div",
+               .ops = &meson_clk_mpll_ops,
+               .parent_names = (const char *[]){ "mpll_prediv" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_mpll2 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL5,
+               .bit_idx = 31,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll2",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mpll2_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_mpll3_div = {
+       .data = &(struct meson_clk_mpll_data){
+               .sdm = {
+                       .reg_off = HHI_MPLL_CNTL7,
+                       .shift   = 0,
+                       .width   = 14,
+               },
+               .sdm_en = {
+                       .reg_off = HHI_MPLL_CNTL7,
+                       .shift   = 30,
+                       .width   = 1,
+               },
+               .n2 = {
+                       .reg_off = HHI_MPLL_CNTL7,
+                       .shift   = 20,
+                       .width   = 9,
+               },
+               .ssen = {
+                       .reg_off = HHI_MPLL_CNTL7,
+                       .shift   = 29,
+                       .width   = 1,
+               },
+               .lock = &meson_clk_lock,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll3_div",
+               .ops = &meson_clk_mpll_ops,
+               .parent_names = (const char *[]){ "mpll_prediv" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap g12a_mpll3 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPLL_CNTL7,
+               .bit_idx = 31,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mpll3",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mpll3_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static u32 mux_table_clk81[]   = { 0, 2, 3, 4, 5, 6, 7 };
+static const char * const clk81_parent_names[] = {
+       IN_PREFIX "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
+       "fclk_div3", "fclk_div5"
+};
+
+static struct clk_regmap g12a_mpeg_clk_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_MPEG_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 12,
+               .table = mux_table_clk81,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mpeg_clk_sel",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = clk81_parent_names,
+               .num_parents = ARRAY_SIZE(clk81_parent_names),
+       },
+};
+
+static struct clk_regmap g12a_mpeg_clk_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_MPEG_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mpeg_clk_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "mpeg_clk_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_clk81 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MPEG_CLK_CNTL,
+               .bit_idx = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "clk81",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mpeg_clk_div" },
+               .num_parents = 1,
+               .flags = (CLK_SET_RATE_PARENT | CLK_IS_CRITICAL),
+       },
+};
+
+static const char * const g12a_sd_emmc_clk0_parent_names[] = {
+       IN_PREFIX "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7",
+
+       /*
+        * Following these parent clocks, we should also have had mpll2, mpll3
+        * and gp0_pll but these clocks are too precious to be used here. All
+        * the necessary rates for MMC and NAND operation can be acheived using
+        * g12a_ee_core or fclk_div clocks
+        */
+};
+
+/* SDIO clock */
+static struct clk_regmap g12a_sd_emmc_a_clk0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SD_EMMC_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 9,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "sd_emmc_a_clk0_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_sd_emmc_clk0_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_names),
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_sd_emmc_a_clk0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SD_EMMC_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "sd_emmc_a_clk0_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "sd_emmc_a_clk0_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_sd_emmc_a_clk0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SD_EMMC_CLK_CNTL,
+               .bit_idx = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "sd_emmc_a_clk0",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "sd_emmc_a_clk0_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+/* SDcard clock */
+static struct clk_regmap g12a_sd_emmc_b_clk0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_SD_EMMC_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 25,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "sd_emmc_b_clk0_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_sd_emmc_clk0_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_names),
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_sd_emmc_b_clk0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_SD_EMMC_CLK_CNTL,
+               .shift = 16,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "sd_emmc_b_clk0_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "sd_emmc_b_clk0_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_sd_emmc_b_clk0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_SD_EMMC_CLK_CNTL,
+               .bit_idx = 23,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "sd_emmc_b_clk0",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "sd_emmc_b_clk0_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+/* EMMC/NAND clock */
+static struct clk_regmap g12a_sd_emmc_c_clk0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_NAND_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 9,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "sd_emmc_c_clk0_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_sd_emmc_clk0_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_sd_emmc_clk0_parent_names),
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_sd_emmc_c_clk0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_NAND_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "sd_emmc_c_clk0_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "sd_emmc_c_clk0_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_sd_emmc_c_clk0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_NAND_CLK_CNTL,
+               .bit_idx = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "sd_emmc_c_clk0",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "sd_emmc_c_clk0_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+/* VPU Clock */
+
+static const char * const g12a_vpu_parent_names[] = {
+       "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7",
+       "mpll1", "vid_pll", "hifi_pll", "gp0_pll",
+};
+
+static struct clk_regmap g12a_vpu_0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VPU_CLK_CNTL,
+               .mask = 0x3,
+               .shift = 9,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vpu_0_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_vpu_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_vpu_parent_names),
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_regmap g12a_vpu_0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VPU_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vpu_0_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "vpu_0_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_vpu_0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VPU_CLK_CNTL,
+               .bit_idx = 8,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vpu_0",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vpu_0_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vpu_1_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VPU_CLK_CNTL,
+               .mask = 0x3,
+               .shift = 25,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vpu_1_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_vpu_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_vpu_parent_names),
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_regmap g12a_vpu_1_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VPU_CLK_CNTL,
+               .shift = 16,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vpu_1_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "vpu_1_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_vpu_1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VPU_CLK_CNTL,
+               .bit_idx = 24,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vpu_1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vpu_1_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vpu = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VPU_CLK_CNTL,
+               .mask = 1,
+               .shift = 31,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vpu",
+               .ops = &clk_regmap_mux_ops,
+               /*
+                * bit 31 selects from 2 possible parents:
+                * vpu_0 or vpu_1
+                */
+               .parent_names = (const char *[]){ "vpu_0", "vpu_1" },
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+/* VAPB Clock */
+
+static const char * const g12a_vapb_parent_names[] = {
+       "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7",
+       "mpll1", "vid_pll", "mpll2", "fclk_div2p5",
+};
+
+static struct clk_regmap g12a_vapb_0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .mask = 0x3,
+               .shift = 9,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vapb_0_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_vapb_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_vapb_parent_names),
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_regmap g12a_vapb_0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vapb_0_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "vapb_0_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_vapb_0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .bit_idx = 8,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vapb_0",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vapb_0_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vapb_1_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .mask = 0x3,
+               .shift = 25,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vapb_1_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_vapb_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_vapb_parent_names),
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_regmap g12a_vapb_1_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .shift = 16,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vapb_1_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "vapb_1_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_vapb_1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .bit_idx = 24,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vapb_1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vapb_1_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vapb_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .mask = 1,
+               .shift = 31,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vapb_sel",
+               .ops = &clk_regmap_mux_ops,
+               /*
+                * bit 31 selects from 2 possible parents:
+                * vapb_0 or vapb_1
+                */
+               .parent_names = (const char *[]){ "vapb_0", "vapb_1" },
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_regmap g12a_vapb = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VAPBCLK_CNTL,
+               .bit_idx = 30,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vapb",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vapb_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+/* Video Clocks */
+
+static struct clk_regmap g12a_vid_pll_div = {
+       .data = &(struct meson_vid_pll_div_data){
+               .val = {
+                       .reg_off = HHI_VID_PLL_CLK_DIV,
+                       .shift   = 0,
+                       .width   = 15,
+               },
+               .sel = {
+                       .reg_off = HHI_VID_PLL_CLK_DIV,
+                       .shift   = 16,
+                       .width   = 2,
+               },
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vid_pll_div",
+               .ops = &meson_vid_pll_div_ro_ops,
+               .parent_names = (const char *[]){ "hdmi_pll" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static const char * const g12a_vid_pll_parent_names[] = { "vid_pll_div",
+                                                         "hdmi_pll" };
+
+static struct clk_regmap g12a_vid_pll_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VID_PLL_CLK_DIV,
+               .mask = 0x1,
+               .shift = 18,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vid_pll_sel",
+               .ops = &clk_regmap_mux_ops,
+               /*
+                * bit 18 selects from 2 possible parents:
+                * vid_pll_div or hdmi_pll
+                */
+               .parent_names = g12a_vid_pll_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_vid_pll_parent_names),
+               .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap g12a_vid_pll = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_PLL_CLK_DIV,
+               .bit_idx = 19,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vid_pll",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vid_pll_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static const char * const g12a_vclk_parent_names[] = {
+       "vid_pll", "gp0_pll", "hifi_pll", "mpll1", "fclk_div3", "fclk_div4",
+       "fclk_div5", "fclk_div7"
+};
+
+static struct clk_regmap g12a_vclk_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VID_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 16,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_vclk_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_vclk_parent_names),
+               .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap g12a_vclk2_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VIID_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 16,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk2_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_vclk_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_vclk_parent_names),
+               .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap g12a_vclk_input = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_DIV,
+               .bit_idx = 16,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk_input",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vclk_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vclk2_input = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VIID_CLK_DIV,
+               .bit_idx = 16,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk2_input",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vclk2_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vclk_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VID_CLK_DIV,
+               .shift = 0,
+               .width = 8,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "vclk_input" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap g12a_vclk2_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_VIID_CLK_DIV,
+               .shift = 0,
+               .width = 8,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk2_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "vclk2_input" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap g12a_vclk = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL,
+               .bit_idx = 19,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vclk_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vclk2 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VIID_CLK_CNTL,
+               .bit_idx = 19,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk2",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vclk2_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vclk_div1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL,
+               .bit_idx = 0,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk_div1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vclk" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vclk_div2_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL,
+               .bit_idx = 1,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk_div2_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vclk" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vclk_div4_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL,
+               .bit_idx = 2,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk_div4_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vclk" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vclk_div6_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL,
+               .bit_idx = 3,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk_div6_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vclk" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vclk_div12_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL,
+               .bit_idx = 4,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk_div12_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vclk" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vclk2_div1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VIID_CLK_CNTL,
+               .bit_idx = 0,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk2_div1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vclk2" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vclk2_div2_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VIID_CLK_CNTL,
+               .bit_idx = 1,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk2_div2_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vclk2" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vclk2_div4_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VIID_CLK_CNTL,
+               .bit_idx = 2,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk2_div4_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vclk2" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vclk2_div6_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VIID_CLK_CNTL,
+               .bit_idx = 3,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk2_div6_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vclk2" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_vclk2_div12_en = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VIID_CLK_CNTL,
+               .bit_idx = 4,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "vclk2_div12_en",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "vclk2" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_fixed_factor g12a_vclk_div2 = {
+       .mult = 1,
+       .div = 2,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk_div2",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "vclk_div2_en" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor g12a_vclk_div4 = {
+       .mult = 1,
+       .div = 4,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk_div4",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "vclk_div4_en" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor g12a_vclk_div6 = {
+       .mult = 1,
+       .div = 6,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk_div6",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "vclk_div6_en" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor g12a_vclk_div12 = {
+       .mult = 1,
+       .div = 12,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk_div12",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "vclk_div12_en" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor g12a_vclk2_div2 = {
+       .mult = 1,
+       .div = 2,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk2_div2",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "vclk2_div2_en" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor g12a_vclk2_div4 = {
+       .mult = 1,
+       .div = 4,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk2_div4",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "vclk2_div4_en" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor g12a_vclk2_div6 = {
+       .mult = 1,
+       .div = 6,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk2_div6",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "vclk2_div6_en" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_fixed_factor g12a_vclk2_div12 = {
+       .mult = 1,
+       .div = 12,
+       .hw.init = &(struct clk_init_data){
+               .name = "vclk2_div12",
+               .ops = &clk_fixed_factor_ops,
+               .parent_names = (const char *[]){ "vclk2_div12_en" },
+               .num_parents = 1,
+       },
+};
+
+static u32 mux_table_cts_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
+static const char * const g12a_cts_parent_names[] = {
+       "vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6",
+       "vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4",
+       "vclk2_div6", "vclk2_div12"
+};
+
+static struct clk_regmap g12a_cts_enci_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VID_CLK_DIV,
+               .mask = 0xf,
+               .shift = 28,
+               .table = mux_table_cts_sel,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cts_enci_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_cts_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_cts_parent_names),
+               .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap g12a_cts_encp_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VID_CLK_DIV,
+               .mask = 0xf,
+               .shift = 20,
+               .table = mux_table_cts_sel,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cts_encp_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_cts_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_cts_parent_names),
+               .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap g12a_cts_vdac_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_VIID_CLK_DIV,
+               .mask = 0xf,
+               .shift = 28,
+               .table = mux_table_cts_sel,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "cts_vdac_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_cts_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_cts_parent_names),
+               .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
+       },
+};
+
+/* TOFIX: add support for cts_tcon */
+static u32 mux_table_hdmi_tx_sel[] = { 0, 1, 2, 3, 4, 8, 9, 10, 11, 12 };
+static const char * const g12a_cts_hdmi_tx_parent_names[] = {
+       "vclk_div1", "vclk_div2", "vclk_div4", "vclk_div6",
+       "vclk_div12", "vclk2_div1", "vclk2_div2", "vclk2_div4",
+       "vclk2_div6", "vclk2_div12"
+};
+
+static struct clk_regmap g12a_hdmi_tx_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_HDMI_CLK_CNTL,
+               .mask = 0xf,
+               .shift = 16,
+               .table = mux_table_hdmi_tx_sel,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "hdmi_tx_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_cts_hdmi_tx_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_cts_hdmi_tx_parent_names),
+               .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap g12a_cts_enci = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL2,
+               .bit_idx = 0,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "cts_enci",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "cts_enci_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_cts_encp = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL2,
+               .bit_idx = 2,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "cts_encp",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "cts_encp_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_cts_vdac = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL2,
+               .bit_idx = 4,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "cts_vdac",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "cts_vdac_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+static struct clk_regmap g12a_hdmi_tx = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_VID_CLK_CNTL2,
+               .bit_idx = 5,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "hdmi_tx",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "hdmi_tx_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+/* HDMI Clocks */
+
+static const char * const g12a_hdmi_parent_names[] = {
+       IN_PREFIX "xtal", "fclk_div4", "fclk_div3", "fclk_div5"
+};
+
+static struct clk_regmap g12a_hdmi_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_HDMI_CLK_CNTL,
+               .mask = 0x3,
+               .shift = 9,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "hdmi_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_hdmi_parent_names,
+               .num_parents = ARRAY_SIZE(g12a_hdmi_parent_names),
+               .flags = CLK_SET_RATE_NO_REPARENT | CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap g12a_hdmi_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_HDMI_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "hdmi_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "hdmi_sel" },
+               .num_parents = 1,
+               .flags = CLK_GET_RATE_NOCACHE,
+       },
+};
+
+static struct clk_regmap g12a_hdmi = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_HDMI_CLK_CNTL,
+               .bit_idx = 8,
+       },
+       .hw.init = &(struct clk_init_data) {
+               .name = "hdmi",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "hdmi_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT | CLK_IGNORE_UNUSED,
+       },
+};
+
+/*
+ * The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
+ * muxed by a glitch-free switch.
+ */
+
+static const char * const g12a_mali_0_1_parent_names[] = {
+       IN_PREFIX "xtal", "gp0_pll", "hihi_pll", "fclk_div2p5",
+       "fclk_div3", "fclk_div4", "fclk_div5", "fclk_div7"
+};
+
+static struct clk_regmap g12a_mali_0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 9,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_0_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_mali_0_1_parent_names,
+               .num_parents = 8,
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_regmap g12a_mali_0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_0_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "mali_0_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_regmap g12a_mali_0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .bit_idx = 8,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_0",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mali_0_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap g12a_mali_1_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 25,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_1_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_mali_0_1_parent_names,
+               .num_parents = 8,
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_regmap g12a_mali_1_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .shift = 16,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_1_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "mali_1_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+static struct clk_regmap g12a_mali_1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .bit_idx = 24,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mali_1_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static const char * const g12a_mali_parent_names[] = {
+       "mali_0", "mali_1"
+};
+
+static struct clk_regmap g12a_mali = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .mask = 1,
+               .shift = 31,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mali",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = g12a_mali_parent_names,
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_NO_REPARENT,
+       },
+};
+
+/* Everything Else (EE) domain gates */
+static MESON_GATE(g12a_ddr,                    HHI_GCLK_MPEG0, 0);
+static MESON_GATE(g12a_dos,                    HHI_GCLK_MPEG0, 1);
+static MESON_GATE(g12a_audio_locker,           HHI_GCLK_MPEG0, 2);
+static MESON_GATE(g12a_mipi_dsi_host,          HHI_GCLK_MPEG0, 3);
+static MESON_GATE(g12a_eth_phy,                        HHI_GCLK_MPEG0, 4);
+static MESON_GATE(g12a_isa,                    HHI_GCLK_MPEG0, 5);
+static MESON_GATE(g12a_pl301,                  HHI_GCLK_MPEG0, 6);
+static MESON_GATE(g12a_periphs,                        HHI_GCLK_MPEG0, 7);
+static MESON_GATE(g12a_spicc_0,                        HHI_GCLK_MPEG0, 8);
+static MESON_GATE(g12a_i2c,                    HHI_GCLK_MPEG0, 9);
+static MESON_GATE(g12a_sana,                   HHI_GCLK_MPEG0, 10);
+static MESON_GATE(g12a_sd,                     HHI_GCLK_MPEG0, 11);
+static MESON_GATE(g12a_rng0,                   HHI_GCLK_MPEG0, 12);
+static MESON_GATE(g12a_uart0,                  HHI_GCLK_MPEG0, 13);
+static MESON_GATE(g12a_spicc_1,                        HHI_GCLK_MPEG0, 14);
+static MESON_GATE(g12a_hiu_reg,                        HHI_GCLK_MPEG0, 19);
+static MESON_GATE(g12a_mipi_dsi_phy,           HHI_GCLK_MPEG0, 20);
+static MESON_GATE(g12a_assist_misc,            HHI_GCLK_MPEG0, 23);
+static MESON_GATE(g12a_emmc_a,                 HHI_GCLK_MPEG0, 4);
+static MESON_GATE(g12a_emmc_b,                 HHI_GCLK_MPEG0, 25);
+static MESON_GATE(g12a_emmc_c,                 HHI_GCLK_MPEG0, 26);
+static MESON_GATE(g12a_audio_codec,            HHI_GCLK_MPEG0, 28);
+
+static MESON_GATE(g12a_audio,                  HHI_GCLK_MPEG1, 0);
+static MESON_GATE(g12a_eth_core,               HHI_GCLK_MPEG1, 3);
+static MESON_GATE(g12a_demux,                  HHI_GCLK_MPEG1, 4);
+static MESON_GATE(g12a_audio_ififo,            HHI_GCLK_MPEG1, 11);
+static MESON_GATE(g12a_adc,                    HHI_GCLK_MPEG1, 13);
+static MESON_GATE(g12a_uart1,                  HHI_GCLK_MPEG1, 16);
+static MESON_GATE(g12a_g2d,                    HHI_GCLK_MPEG1, 20);
+static MESON_GATE(g12a_reset,                  HHI_GCLK_MPEG1, 23);
+static MESON_GATE(g12a_pcie_comb,              HHI_GCLK_MPEG1, 24);
+static MESON_GATE(g12a_parser,                 HHI_GCLK_MPEG1, 25);
+static MESON_GATE(g12a_usb_general,            HHI_GCLK_MPEG1, 26);
+static MESON_GATE(g12a_pcie_phy,               HHI_GCLK_MPEG1, 27);
+static MESON_GATE(g12a_ahb_arb0,               HHI_GCLK_MPEG1, 29);
+
+static MESON_GATE(g12a_ahb_data_bus,           HHI_GCLK_MPEG2, 1);
+static MESON_GATE(g12a_ahb_ctrl_bus,           HHI_GCLK_MPEG2, 2);
+static MESON_GATE(g12a_htx_hdcp22,             HHI_GCLK_MPEG2, 3);
+static MESON_GATE(g12a_htx_pclk,               HHI_GCLK_MPEG2, 4);
+static MESON_GATE(g12a_bt656,                  HHI_GCLK_MPEG2, 6);
+static MESON_GATE(g12a_usb1_to_ddr,            HHI_GCLK_MPEG2, 8);
+static MESON_GATE(g12a_mmc_pclk,               HHI_GCLK_MPEG2, 11);
+static MESON_GATE(g12a_uart2,                  HHI_GCLK_MPEG2, 15);
+static MESON_GATE(g12a_vpu_intr,               HHI_GCLK_MPEG2, 25);
+static MESON_GATE(g12a_gic,                    HHI_GCLK_MPEG2, 30);
+
+static MESON_GATE(g12a_vclk2_venci0,           HHI_GCLK_OTHER, 1);
+static MESON_GATE(g12a_vclk2_venci1,           HHI_GCLK_OTHER, 2);
+static MESON_GATE(g12a_vclk2_vencp0,           HHI_GCLK_OTHER, 3);
+static MESON_GATE(g12a_vclk2_vencp1,           HHI_GCLK_OTHER, 4);
+static MESON_GATE(g12a_vclk2_venct0,           HHI_GCLK_OTHER, 5);
+static MESON_GATE(g12a_vclk2_venct1,           HHI_GCLK_OTHER, 6);
+static MESON_GATE(g12a_vclk2_other,            HHI_GCLK_OTHER, 7);
+static MESON_GATE(g12a_vclk2_enci,             HHI_GCLK_OTHER, 8);
+static MESON_GATE(g12a_vclk2_encp,             HHI_GCLK_OTHER, 9);
+static MESON_GATE(g12a_dac_clk,                        HHI_GCLK_OTHER, 10);
+static MESON_GATE(g12a_aoclk_gate,             HHI_GCLK_OTHER, 14);
+static MESON_GATE(g12a_iec958_gate,            HHI_GCLK_OTHER, 16);
+static MESON_GATE(g12a_enc480p,                        HHI_GCLK_OTHER, 20);
+static MESON_GATE(g12a_rng1,                   HHI_GCLK_OTHER, 21);
+static MESON_GATE(g12a_vclk2_enct,             HHI_GCLK_OTHER, 22);
+static MESON_GATE(g12a_vclk2_encl,             HHI_GCLK_OTHER, 23);
+static MESON_GATE(g12a_vclk2_venclmmc,         HHI_GCLK_OTHER, 24);
+static MESON_GATE(g12a_vclk2_vencl,            HHI_GCLK_OTHER, 25);
+static MESON_GATE(g12a_vclk2_other1,           HHI_GCLK_OTHER, 26);
+
+static MESON_GATE_RO(g12a_dma,                 HHI_GCLK_OTHER2, 0);
+static MESON_GATE_RO(g12a_efuse,               HHI_GCLK_OTHER2, 1);
+static MESON_GATE_RO(g12a_rom_boot,            HHI_GCLK_OTHER2, 2);
+static MESON_GATE_RO(g12a_reset_sec,           HHI_GCLK_OTHER2, 3);
+static MESON_GATE_RO(g12a_sec_ahb_apb3,                HHI_GCLK_OTHER2, 4);
+
+/* Array of all clocks provided by this provider */
+static struct clk_hw_onecell_data g12a_hw_onecell_data = {
+       .hws = {
+               [CLKID_SYS_PLL]                 = &g12a_sys_pll.hw,
+               [CLKID_FIXED_PLL]               = &g12a_fixed_pll.hw,
+               [CLKID_FCLK_DIV2]               = &g12a_fclk_div2.hw,
+               [CLKID_FCLK_DIV3]               = &g12a_fclk_div3.hw,
+               [CLKID_FCLK_DIV4]               = &g12a_fclk_div4.hw,
+               [CLKID_FCLK_DIV5]               = &g12a_fclk_div5.hw,
+               [CLKID_FCLK_DIV7]               = &g12a_fclk_div7.hw,
+               [CLKID_FCLK_DIV2P5]             = &g12a_fclk_div2p5.hw,
+               [CLKID_GP0_PLL]                 = &g12a_gp0_pll.hw,
+               [CLKID_MPEG_SEL]                = &g12a_mpeg_clk_sel.hw,
+               [CLKID_MPEG_DIV]                = &g12a_mpeg_clk_div.hw,
+               [CLKID_CLK81]                   = &g12a_clk81.hw,
+               [CLKID_MPLL0]                   = &g12a_mpll0.hw,
+               [CLKID_MPLL1]                   = &g12a_mpll1.hw,
+               [CLKID_MPLL2]                   = &g12a_mpll2.hw,
+               [CLKID_MPLL3]                   = &g12a_mpll3.hw,
+               [CLKID_DDR]                     = &g12a_ddr.hw,
+               [CLKID_DOS]                     = &g12a_dos.hw,
+               [CLKID_AUDIO_LOCKER]            = &g12a_audio_locker.hw,
+               [CLKID_MIPI_DSI_HOST]           = &g12a_mipi_dsi_host.hw,
+               [CLKID_ETH_PHY]                 = &g12a_eth_phy.hw,
+               [CLKID_ISA]                     = &g12a_isa.hw,
+               [CLKID_PL301]                   = &g12a_pl301.hw,
+               [CLKID_PERIPHS]                 = &g12a_periphs.hw,
+               [CLKID_SPICC0]                  = &g12a_spicc_0.hw,
+               [CLKID_I2C]                     = &g12a_i2c.hw,
+               [CLKID_SANA]                    = &g12a_sana.hw,
+               [CLKID_SD]                      = &g12a_sd.hw,
+               [CLKID_RNG0]                    = &g12a_rng0.hw,
+               [CLKID_UART0]                   = &g12a_uart0.hw,
+               [CLKID_SPICC1]                  = &g12a_spicc_1.hw,
+               [CLKID_HIU_IFACE]               = &g12a_hiu_reg.hw,
+               [CLKID_MIPI_DSI_PHY]            = &g12a_mipi_dsi_phy.hw,
+               [CLKID_ASSIST_MISC]             = &g12a_assist_misc.hw,
+               [CLKID_SD_EMMC_A]               = &g12a_emmc_a.hw,
+               [CLKID_SD_EMMC_B]               = &g12a_emmc_b.hw,
+               [CLKID_SD_EMMC_C]               = &g12a_emmc_c.hw,
+               [CLKID_AUDIO_CODEC]             = &g12a_audio_codec.hw,
+               [CLKID_AUDIO]                   = &g12a_audio.hw,
+               [CLKID_ETH]                     = &g12a_eth_core.hw,
+               [CLKID_DEMUX]                   = &g12a_demux.hw,
+               [CLKID_AUDIO_IFIFO]             = &g12a_audio_ififo.hw,
+               [CLKID_ADC]                     = &g12a_adc.hw,
+               [CLKID_UART1]                   = &g12a_uart1.hw,
+               [CLKID_G2D]                     = &g12a_g2d.hw,
+               [CLKID_RESET]                   = &g12a_reset.hw,
+               [CLKID_PCIE_COMB]               = &g12a_pcie_comb.hw,
+               [CLKID_PARSER]                  = &g12a_parser.hw,
+               [CLKID_USB]                     = &g12a_usb_general.hw,
+               [CLKID_PCIE_PHY]                = &g12a_pcie_phy.hw,
+               [CLKID_AHB_ARB0]                = &g12a_ahb_arb0.hw,
+               [CLKID_AHB_DATA_BUS]            = &g12a_ahb_data_bus.hw,
+               [CLKID_AHB_CTRL_BUS]            = &g12a_ahb_ctrl_bus.hw,
+               [CLKID_HTX_HDCP22]              = &g12a_htx_hdcp22.hw,
+               [CLKID_HTX_PCLK]                = &g12a_htx_pclk.hw,
+               [CLKID_BT656]                   = &g12a_bt656.hw,
+               [CLKID_USB1_DDR_BRIDGE]         = &g12a_usb1_to_ddr.hw,
+               [CLKID_MMC_PCLK]                = &g12a_mmc_pclk.hw,
+               [CLKID_UART2]                   = &g12a_uart2.hw,
+               [CLKID_VPU_INTR]                = &g12a_vpu_intr.hw,
+               [CLKID_GIC]                     = &g12a_gic.hw,
+               [CLKID_SD_EMMC_A_CLK0_SEL]      = &g12a_sd_emmc_a_clk0_sel.hw,
+               [CLKID_SD_EMMC_A_CLK0_DIV]      = &g12a_sd_emmc_a_clk0_div.hw,
+               [CLKID_SD_EMMC_A_CLK0]          = &g12a_sd_emmc_a_clk0.hw,
+               [CLKID_SD_EMMC_B_CLK0_SEL]      = &g12a_sd_emmc_b_clk0_sel.hw,
+               [CLKID_SD_EMMC_B_CLK0_DIV]      = &g12a_sd_emmc_b_clk0_div.hw,
+               [CLKID_SD_EMMC_B_CLK0]          = &g12a_sd_emmc_b_clk0.hw,
+               [CLKID_SD_EMMC_C_CLK0_SEL]      = &g12a_sd_emmc_c_clk0_sel.hw,
+               [CLKID_SD_EMMC_C_CLK0_DIV]      = &g12a_sd_emmc_c_clk0_div.hw,
+               [CLKID_SD_EMMC_C_CLK0]          = &g12a_sd_emmc_c_clk0.hw,
+               [CLKID_MPLL0_DIV]               = &g12a_mpll0_div.hw,
+               [CLKID_MPLL1_DIV]               = &g12a_mpll1_div.hw,
+               [CLKID_MPLL2_DIV]               = &g12a_mpll2_div.hw,
+               [CLKID_MPLL3_DIV]               = &g12a_mpll3_div.hw,
+               [CLKID_FCLK_DIV2_DIV]           = &g12a_fclk_div2_div.hw,
+               [CLKID_FCLK_DIV3_DIV]           = &g12a_fclk_div3_div.hw,
+               [CLKID_FCLK_DIV4_DIV]           = &g12a_fclk_div4_div.hw,
+               [CLKID_FCLK_DIV5_DIV]           = &g12a_fclk_div5_div.hw,
+               [CLKID_FCLK_DIV7_DIV]           = &g12a_fclk_div7_div.hw,
+               [CLKID_FCLK_DIV2P5_DIV]         = &g12a_fclk_div2p5_div.hw,
+               [CLKID_HIFI_PLL]                = &g12a_hifi_pll.hw,
+               [CLKID_VCLK2_VENCI0]            = &g12a_vclk2_venci0.hw,
+               [CLKID_VCLK2_VENCI1]            = &g12a_vclk2_venci1.hw,
+               [CLKID_VCLK2_VENCP0]            = &g12a_vclk2_vencp0.hw,
+               [CLKID_VCLK2_VENCP1]            = &g12a_vclk2_vencp1.hw,
+               [CLKID_VCLK2_VENCT0]            = &g12a_vclk2_venct0.hw,
+               [CLKID_VCLK2_VENCT1]            = &g12a_vclk2_venct1.hw,
+               [CLKID_VCLK2_OTHER]             = &g12a_vclk2_other.hw,
+               [CLKID_VCLK2_ENCI]              = &g12a_vclk2_enci.hw,
+               [CLKID_VCLK2_ENCP]              = &g12a_vclk2_encp.hw,
+               [CLKID_DAC_CLK]                 = &g12a_dac_clk.hw,
+               [CLKID_AOCLK]                   = &g12a_aoclk_gate.hw,
+               [CLKID_IEC958]                  = &g12a_iec958_gate.hw,
+               [CLKID_ENC480P]                 = &g12a_enc480p.hw,
+               [CLKID_RNG1]                    = &g12a_rng1.hw,
+               [CLKID_VCLK2_ENCT]              = &g12a_vclk2_enct.hw,
+               [CLKID_VCLK2_ENCL]              = &g12a_vclk2_encl.hw,
+               [CLKID_VCLK2_VENCLMMC]          = &g12a_vclk2_venclmmc.hw,
+               [CLKID_VCLK2_VENCL]             = &g12a_vclk2_vencl.hw,
+               [CLKID_VCLK2_OTHER1]            = &g12a_vclk2_other1.hw,
+               [CLKID_FIXED_PLL_DCO]           = &g12a_fixed_pll_dco.hw,
+               [CLKID_SYS_PLL_DCO]             = &g12a_sys_pll_dco.hw,
+               [CLKID_GP0_PLL_DCO]             = &g12a_gp0_pll_dco.hw,
+               [CLKID_HIFI_PLL_DCO]            = &g12a_hifi_pll_dco.hw,
+               [CLKID_DMA]                     = &g12a_dma.hw,
+               [CLKID_EFUSE]                   = &g12a_efuse.hw,
+               [CLKID_ROM_BOOT]                = &g12a_rom_boot.hw,
+               [CLKID_RESET_SEC]               = &g12a_reset_sec.hw,
+               [CLKID_SEC_AHB_APB3]            = &g12a_sec_ahb_apb3.hw,
+               [CLKID_MPLL_PREDIV]             = &g12a_mpll_prediv.hw,
+               [CLKID_VPU_0_SEL]               = &g12a_vpu_0_sel.hw,
+               [CLKID_VPU_0_DIV]               = &g12a_vpu_0_div.hw,
+               [CLKID_VPU_0]                   = &g12a_vpu_0.hw,
+               [CLKID_VPU_1_SEL]               = &g12a_vpu_1_sel.hw,
+               [CLKID_VPU_1_DIV]               = &g12a_vpu_1_div.hw,
+               [CLKID_VPU_1]                   = &g12a_vpu_1.hw,
+               [CLKID_VPU]                     = &g12a_vpu.hw,
+               [CLKID_VAPB_0_SEL]              = &g12a_vapb_0_sel.hw,
+               [CLKID_VAPB_0_DIV]              = &g12a_vapb_0_div.hw,
+               [CLKID_VAPB_0]                  = &g12a_vapb_0.hw,
+               [CLKID_VAPB_1_SEL]              = &g12a_vapb_1_sel.hw,
+               [CLKID_VAPB_1_DIV]              = &g12a_vapb_1_div.hw,
+               [CLKID_VAPB_1]                  = &g12a_vapb_1.hw,
+               [CLKID_VAPB_SEL]                = &g12a_vapb_sel.hw,
+               [CLKID_VAPB]                    = &g12a_vapb.hw,
+               [CLKID_HDMI_PLL_DCO]            = &g12a_hdmi_pll_dco.hw,
+               [CLKID_HDMI_PLL_OD]             = &g12a_hdmi_pll_od.hw,
+               [CLKID_HDMI_PLL_OD2]            = &g12a_hdmi_pll_od2.hw,
+               [CLKID_HDMI_PLL]                = &g12a_hdmi_pll.hw,
+               [CLKID_VID_PLL]                 = &g12a_vid_pll_div.hw,
+               [CLKID_VID_PLL_SEL]             = &g12a_vid_pll_sel.hw,
+               [CLKID_VID_PLL_DIV]             = &g12a_vid_pll.hw,
+               [CLKID_VCLK_SEL]                = &g12a_vclk_sel.hw,
+               [CLKID_VCLK2_SEL]               = &g12a_vclk2_sel.hw,
+               [CLKID_VCLK_INPUT]              = &g12a_vclk_input.hw,
+               [CLKID_VCLK2_INPUT]             = &g12a_vclk2_input.hw,
+               [CLKID_VCLK_DIV]                = &g12a_vclk_div.hw,
+               [CLKID_VCLK2_DIV]               = &g12a_vclk2_div.hw,
+               [CLKID_VCLK]                    = &g12a_vclk.hw,
+               [CLKID_VCLK2]                   = &g12a_vclk2.hw,
+               [CLKID_VCLK_DIV1]               = &g12a_vclk_div1.hw,
+               [CLKID_VCLK_DIV2_EN]            = &g12a_vclk_div2_en.hw,
+               [CLKID_VCLK_DIV4_EN]            = &g12a_vclk_div4_en.hw,
+               [CLKID_VCLK_DIV6_EN]            = &g12a_vclk_div6_en.hw,
+               [CLKID_VCLK_DIV12_EN]           = &g12a_vclk_div12_en.hw,
+               [CLKID_VCLK2_DIV1]              = &g12a_vclk2_div1.hw,
+               [CLKID_VCLK2_DIV2_EN]           = &g12a_vclk2_div2_en.hw,
+               [CLKID_VCLK2_DIV4_EN]           = &g12a_vclk2_div4_en.hw,
+               [CLKID_VCLK2_DIV6_EN]           = &g12a_vclk2_div6_en.hw,
+               [CLKID_VCLK2_DIV12_EN]          = &g12a_vclk2_div12_en.hw,
+               [CLKID_VCLK_DIV2]               = &g12a_vclk_div2.hw,
+               [CLKID_VCLK_DIV4]               = &g12a_vclk_div4.hw,
+               [CLKID_VCLK_DIV6]               = &g12a_vclk_div6.hw,
+               [CLKID_VCLK_DIV12]              = &g12a_vclk_div12.hw,
+               [CLKID_VCLK2_DIV2]              = &g12a_vclk2_div2.hw,
+               [CLKID_VCLK2_DIV4]              = &g12a_vclk2_div4.hw,
+               [CLKID_VCLK2_DIV6]              = &g12a_vclk2_div6.hw,
+               [CLKID_VCLK2_DIV12]             = &g12a_vclk2_div12.hw,
+               [CLKID_CTS_ENCI_SEL]            = &g12a_cts_enci_sel.hw,
+               [CLKID_CTS_ENCP_SEL]            = &g12a_cts_encp_sel.hw,
+               [CLKID_CTS_VDAC_SEL]            = &g12a_cts_vdac_sel.hw,
+               [CLKID_HDMI_TX_SEL]             = &g12a_hdmi_tx_sel.hw,
+               [CLKID_CTS_ENCI]                = &g12a_cts_enci.hw,
+               [CLKID_CTS_ENCP]                = &g12a_cts_encp.hw,
+               [CLKID_CTS_VDAC]                = &g12a_cts_vdac.hw,
+               [CLKID_HDMI_TX]                 = &g12a_hdmi_tx.hw,
+               [CLKID_HDMI_SEL]                = &g12a_hdmi_sel.hw,
+               [CLKID_HDMI_DIV]                = &g12a_hdmi_div.hw,
+               [CLKID_HDMI]                    = &g12a_hdmi.hw,
+               [CLKID_MALI_0_SEL]              = &g12a_mali_0_sel.hw,
+               [CLKID_MALI_0_DIV]              = &g12a_mali_0_div.hw,
+               [CLKID_MALI_0]                  = &g12a_mali_0.hw,
+               [CLKID_MALI_1_SEL]              = &g12a_mali_1_sel.hw,
+               [CLKID_MALI_1_DIV]              = &g12a_mali_1_div.hw,
+               [CLKID_MALI_1]                  = &g12a_mali_1.hw,
+               [CLKID_MALI]                    = &g12a_mali.hw,
+               [CLKID_MPLL_5OM_DIV]            = &g12a_mpll_50m_div.hw,
+               [CLKID_MPLL_5OM]                = &g12a_mpll_50m.hw,
+               [NR_CLKS]                       = NULL,
+       },
+       .num = NR_CLKS,
+};
+
+/* Convenience table to populate regmap in .probe */
+static struct clk_regmap *const g12a_clk_regmaps[] = {
+       &g12a_clk81,
+       &g12a_dos,
+       &g12a_ddr,
+       &g12a_audio_locker,
+       &g12a_mipi_dsi_host,
+       &g12a_eth_phy,
+       &g12a_isa,
+       &g12a_pl301,
+       &g12a_periphs,
+       &g12a_spicc_0,
+       &g12a_i2c,
+       &g12a_sana,
+       &g12a_sd,
+       &g12a_rng0,
+       &g12a_uart0,
+       &g12a_spicc_1,
+       &g12a_hiu_reg,
+       &g12a_mipi_dsi_phy,
+       &g12a_assist_misc,
+       &g12a_emmc_a,
+       &g12a_emmc_b,
+       &g12a_emmc_c,
+       &g12a_audio_codec,
+       &g12a_audio,
+       &g12a_eth_core,
+       &g12a_demux,
+       &g12a_audio_ififo,
+       &g12a_adc,
+       &g12a_uart1,
+       &g12a_g2d,
+       &g12a_reset,
+       &g12a_pcie_comb,
+       &g12a_parser,
+       &g12a_usb_general,
+       &g12a_pcie_phy,
+       &g12a_ahb_arb0,
+       &g12a_ahb_data_bus,
+       &g12a_ahb_ctrl_bus,
+       &g12a_htx_hdcp22,
+       &g12a_htx_pclk,
+       &g12a_bt656,
+       &g12a_usb1_to_ddr,
+       &g12a_mmc_pclk,
+       &g12a_vpu_intr,
+       &g12a_gic,
+       &g12a_sd_emmc_a_clk0,
+       &g12a_sd_emmc_b_clk0,
+       &g12a_sd_emmc_c_clk0,
+       &g12a_mpeg_clk_div,
+       &g12a_sd_emmc_a_clk0_div,
+       &g12a_sd_emmc_b_clk0_div,
+       &g12a_sd_emmc_c_clk0_div,
+       &g12a_mpeg_clk_sel,
+       &g12a_sd_emmc_a_clk0_sel,
+       &g12a_sd_emmc_b_clk0_sel,
+       &g12a_sd_emmc_c_clk0_sel,
+       &g12a_mpll0,
+       &g12a_mpll1,
+       &g12a_mpll2,
+       &g12a_mpll3,
+       &g12a_mpll0_div,
+       &g12a_mpll1_div,
+       &g12a_mpll2_div,
+       &g12a_mpll3_div,
+       &g12a_fixed_pll,
+       &g12a_sys_pll,
+       &g12a_gp0_pll,
+       &g12a_hifi_pll,
+       &g12a_vclk2_venci0,
+       &g12a_vclk2_venci1,
+       &g12a_vclk2_vencp0,
+       &g12a_vclk2_vencp1,
+       &g12a_vclk2_venct0,
+       &g12a_vclk2_venct1,
+       &g12a_vclk2_other,
+       &g12a_vclk2_enci,
+       &g12a_vclk2_encp,
+       &g12a_dac_clk,
+       &g12a_aoclk_gate,
+       &g12a_iec958_gate,
+       &g12a_enc480p,
+       &g12a_rng1,
+       &g12a_vclk2_enct,
+       &g12a_vclk2_encl,
+       &g12a_vclk2_venclmmc,
+       &g12a_vclk2_vencl,
+       &g12a_vclk2_other1,
+       &g12a_fixed_pll_dco,
+       &g12a_sys_pll_dco,
+       &g12a_gp0_pll_dco,
+       &g12a_hifi_pll_dco,
+       &g12a_fclk_div2,
+       &g12a_fclk_div3,
+       &g12a_fclk_div4,
+       &g12a_fclk_div5,
+       &g12a_fclk_div7,
+       &g12a_fclk_div2p5,
+       &g12a_dma,
+       &g12a_efuse,
+       &g12a_rom_boot,
+       &g12a_reset_sec,
+       &g12a_sec_ahb_apb3,
+       &g12a_vpu_0_sel,
+       &g12a_vpu_0_div,
+       &g12a_vpu_0,
+       &g12a_vpu_1_sel,
+       &g12a_vpu_1_div,
+       &g12a_vpu_1,
+       &g12a_vpu,
+       &g12a_vapb_0_sel,
+       &g12a_vapb_0_div,
+       &g12a_vapb_0,
+       &g12a_vapb_1_sel,
+       &g12a_vapb_1_div,
+       &g12a_vapb_1,
+       &g12a_vapb_sel,
+       &g12a_vapb,
+       &g12a_hdmi_pll_dco,
+       &g12a_hdmi_pll_od,
+       &g12a_hdmi_pll_od2,
+       &g12a_hdmi_pll,
+       &g12a_vid_pll_div,
+       &g12a_vid_pll_sel,
+       &g12a_vid_pll,
+       &g12a_vclk_sel,
+       &g12a_vclk2_sel,
+       &g12a_vclk_input,
+       &g12a_vclk2_input,
+       &g12a_vclk_div,
+       &g12a_vclk2_div,
+       &g12a_vclk,
+       &g12a_vclk2,
+       &g12a_vclk_div1,
+       &g12a_vclk_div2_en,
+       &g12a_vclk_div4_en,
+       &g12a_vclk_div6_en,
+       &g12a_vclk_div12_en,
+       &g12a_vclk2_div1,
+       &g12a_vclk2_div2_en,
+       &g12a_vclk2_div4_en,
+       &g12a_vclk2_div6_en,
+       &g12a_vclk2_div12_en,
+       &g12a_cts_enci_sel,
+       &g12a_cts_encp_sel,
+       &g12a_cts_vdac_sel,
+       &g12a_hdmi_tx_sel,
+       &g12a_cts_enci,
+       &g12a_cts_encp,
+       &g12a_cts_vdac,
+       &g12a_hdmi_tx,
+       &g12a_hdmi_sel,
+       &g12a_hdmi_div,
+       &g12a_hdmi,
+       &g12a_mali_0_sel,
+       &g12a_mali_0_div,
+       &g12a_mali_0,
+       &g12a_mali_1_sel,
+       &g12a_mali_1_div,
+       &g12a_mali_1,
+       &g12a_mali,
+       &g12a_mpll_50m,
+};
+
+static const struct meson_eeclkc_data g12a_clkc_data = {
+       .regmap_clks = g12a_clk_regmaps,
+       .regmap_clk_num = ARRAY_SIZE(g12a_clk_regmaps),
+       .hw_onecell_data = &g12a_hw_onecell_data
+};
+
+static const struct of_device_id clkc_match_table[] = {
+       { .compatible = "amlogic,g12a-clkc", .data = &g12a_clkc_data },
+       {}
+};
+
+static struct platform_driver g12a_driver = {
+       .probe          = meson_eeclkc_probe,
+       .driver         = {
+               .name   = "g12a-clkc",
+               .of_match_table = clkc_match_table,
+       },
+};
+
+builtin_platform_driver(g12a_driver);
diff --git a/drivers/clk/meson/g12a.h b/drivers/clk/meson/g12a.h
new file mode 100644 (file)
index 0000000..f399dfe
--- /dev/null
@@ -0,0 +1,175 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR MIT) */
+/*
+ * Copyright (c) 2016 Amlogic, Inc.
+ * Author: Michael Turquette <mturquette@baylibre.com>
+ *
+ * Copyright (c) 2018 Amlogic, inc.
+ * Author: Qiufang Dai <qiufang.dai@amlogic.com>
+ * Author: Jian Hu <jian.hu@amlogic.com>
+ *
+ */
+#ifndef __G12A_H
+#define __G12A_H
+
+/*
+ * Clock controller register offsets
+ *
+ * Register offsets from the data sheet must be multiplied by 4 before
+ * adding them to the base address to get the right value.
+ */
+#define HHI_MIPI_CNTL0                 0x000
+#define HHI_MIPI_CNTL1                 0x004
+#define HHI_MIPI_CNTL2                 0x008
+#define HHI_MIPI_STS                   0x00C
+#define HHI_GP0_PLL_CNTL0              0x040
+#define HHI_GP0_PLL_CNTL1              0x044
+#define HHI_GP0_PLL_CNTL2              0x048
+#define HHI_GP0_PLL_CNTL3              0x04C
+#define HHI_GP0_PLL_CNTL4              0x050
+#define HHI_GP0_PLL_CNTL5              0x054
+#define HHI_GP0_PLL_CNTL6              0x058
+#define HHI_GP0_PLL_STS                        0x05C
+#define HHI_PCIE_PLL_CNTL0             0x098
+#define HHI_PCIE_PLL_CNTL1             0x09C
+#define HHI_PCIE_PLL_CNTL2             0x0A0
+#define HHI_PCIE_PLL_CNTL3             0x0A4
+#define HHI_PCIE_PLL_CNTL4             0x0A8
+#define HHI_PCIE_PLL_CNTL5             0x0AC
+#define HHI_PCIE_PLL_STS               0x0B8
+#define HHI_HIFI_PLL_CNTL0             0x0D8
+#define HHI_HIFI_PLL_CNTL1             0x0DC
+#define HHI_HIFI_PLL_CNTL2             0x0E0
+#define HHI_HIFI_PLL_CNTL3             0x0E4
+#define HHI_HIFI_PLL_CNTL4             0x0E8
+#define HHI_HIFI_PLL_CNTL5             0x0EC
+#define HHI_HIFI_PLL_CNTL6             0x0F0
+#define HHI_VIID_CLK_DIV               0x128
+#define HHI_VIID_CLK_CNTL              0x12C
+#define HHI_GCLK_MPEG0                 0x140
+#define HHI_GCLK_MPEG1                 0x144
+#define HHI_GCLK_MPEG2                 0x148
+#define HHI_GCLK_OTHER                 0x150
+#define HHI_GCLK_OTHER2                        0x154
+#define HHI_VID_CLK_DIV                        0x164
+#define HHI_MPEG_CLK_CNTL              0x174
+#define HHI_AUD_CLK_CNTL               0x178
+#define HHI_VID_CLK_CNTL               0x17c
+#define HHI_TS_CLK_CNTL                        0x190
+#define HHI_VID_CLK_CNTL2              0x194
+#define HHI_SYS_CPU_CLK_CNTL0          0x19c
+#define HHI_VID_PLL_CLK_DIV            0x1A0
+#define HHI_MALI_CLK_CNTL              0x1b0
+#define HHI_VPU_CLKC_CNTL              0x1b4
+#define HHI_VPU_CLK_CNTL               0x1bC
+#define HHI_HDMI_CLK_CNTL              0x1CC
+#define HHI_VDEC_CLK_CNTL              0x1E0
+#define HHI_VDEC2_CLK_CNTL             0x1E4
+#define HHI_VDEC3_CLK_CNTL             0x1E8
+#define HHI_VDEC4_CLK_CNTL             0x1EC
+#define HHI_HDCP22_CLK_CNTL            0x1F0
+#define HHI_VAPBCLK_CNTL               0x1F4
+#define HHI_VPU_CLKB_CNTL              0x20C
+#define HHI_GEN_CLK_CNTL               0x228
+#define HHI_VDIN_MEAS_CLK_CNTL         0x250
+#define HHI_MIPIDSI_PHY_CLK_CNTL       0x254
+#define HHI_NAND_CLK_CNTL              0x25C
+#define HHI_SD_EMMC_CLK_CNTL           0x264
+#define HHI_MPLL_CNTL0                 0x278
+#define HHI_MPLL_CNTL1                 0x27C
+#define HHI_MPLL_CNTL2                 0x280
+#define HHI_MPLL_CNTL3                 0x284
+#define HHI_MPLL_CNTL4                 0x288
+#define HHI_MPLL_CNTL5                 0x28c
+#define HHI_MPLL_CNTL6                 0x290
+#define HHI_MPLL_CNTL7                 0x294
+#define HHI_MPLL_CNTL8                 0x298
+#define HHI_FIX_PLL_CNTL0              0x2A0
+#define HHI_FIX_PLL_CNTL1              0x2A4
+#define HHI_FIX_PLL_CNTL3              0x2AC
+#define HHI_SYS_PLL_CNTL0              0x2f4
+#define HHI_SYS_PLL_CNTL1              0x2f8
+#define HHI_SYS_PLL_CNTL2              0x2fc
+#define HHI_SYS_PLL_CNTL3              0x300
+#define HHI_SYS_PLL_CNTL4              0x304
+#define HHI_SYS_PLL_CNTL5              0x308
+#define HHI_SYS_PLL_CNTL6              0x30c
+#define HHI_HDMI_PLL_CNTL0             0x320
+#define HHI_HDMI_PLL_CNTL1             0x324
+#define HHI_HDMI_PLL_CNTL2             0x328
+#define HHI_HDMI_PLL_CNTL3             0x32c
+#define HHI_HDMI_PLL_CNTL4             0x330
+#define HHI_HDMI_PLL_CNTL5             0x334
+#define HHI_HDMI_PLL_CNTL6             0x338
+#define HHI_SPICC_CLK_CNTL             0x3dc
+
+/*
+ * CLKID index values
+ *
+ * These indices are entirely contrived and do not map onto the hardware.
+ * It has now been decided to expose everything by default in the DT header:
+ * include/dt-bindings/clock/g12a-clkc.h. Only the clocks ids we don't want
+ * to expose, such as the internal muxes and dividers of composite clocks,
+ * will remain defined here.
+ */
+#define CLKID_MPEG_SEL                         8
+#define CLKID_MPEG_DIV                         9
+#define CLKID_SD_EMMC_A_CLK0_SEL               63
+#define CLKID_SD_EMMC_A_CLK0_DIV               64
+#define CLKID_SD_EMMC_B_CLK0_SEL               65
+#define CLKID_SD_EMMC_B_CLK0_DIV               66
+#define CLKID_SD_EMMC_C_CLK0_SEL               67
+#define CLKID_SD_EMMC_C_CLK0_DIV               68
+#define CLKID_MPLL0_DIV                                69
+#define CLKID_MPLL1_DIV                                70
+#define CLKID_MPLL2_DIV                                71
+#define CLKID_MPLL3_DIV                                72
+#define CLKID_MPLL_PREDIV                      73
+#define CLKID_FCLK_DIV2_DIV                    75
+#define CLKID_FCLK_DIV3_DIV                    76
+#define CLKID_FCLK_DIV4_DIV                    77
+#define CLKID_FCLK_DIV5_DIV                    78
+#define CLKID_FCLK_DIV7_DIV                    79
+#define CLKID_FCLK_DIV2P5_DIV                  100
+#define CLKID_FIXED_PLL_DCO                    101
+#define CLKID_SYS_PLL_DCO                      102
+#define CLKID_GP0_PLL_DCO                      103
+#define CLKID_HIFI_PLL_DCO                     104
+#define CLKID_VPU_0_DIV                                111
+#define CLKID_VPU_1_DIV                                114
+#define CLKID_VAPB_0_DIV                       118
+#define CLKID_VAPB_1_DIV                       121
+#define CLKID_HDMI_PLL_DCO                     125
+#define CLKID_HDMI_PLL_OD                      126
+#define CLKID_HDMI_PLL_OD2                     127
+#define CLKID_VID_PLL_SEL                      130
+#define CLKID_VID_PLL_DIV                      131
+#define CLKID_VCLK_SEL                         132
+#define CLKID_VCLK2_SEL                                133
+#define CLKID_VCLK_INPUT                       134
+#define CLKID_VCLK2_INPUT                      135
+#define CLKID_VCLK_DIV                         136
+#define CLKID_VCLK2_DIV                                137
+#define CLKID_VCLK_DIV2_EN                     140
+#define CLKID_VCLK_DIV4_EN                     141
+#define CLKID_VCLK_DIV6_EN                     142
+#define CLKID_VCLK_DIV12_EN                    143
+#define CLKID_VCLK2_DIV2_EN                    144
+#define CLKID_VCLK2_DIV4_EN                    145
+#define CLKID_VCLK2_DIV6_EN                    146
+#define CLKID_VCLK2_DIV12_EN                   147
+#define CLKID_CTS_ENCI_SEL                     158
+#define CLKID_CTS_ENCP_SEL                     159
+#define CLKID_CTS_VDAC_SEL                     160
+#define CLKID_HDMI_TX_SEL                      161
+#define CLKID_HDMI_SEL                         166
+#define CLKID_HDMI_DIV                         167
+#define CLKID_MALI_0_DIV                       170
+#define CLKID_MALI_1_DIV                       173
+#define CLKID_MPLL_5OM_DIV                     176
+
+#define NR_CLKS                                        178
+
+/* include the CLKIDs that have been made part of the DT binding */
+#include <dt-bindings/clock/g12a-clkc.h>
+
+#endif /* __G12A_H */
diff --git a/drivers/clk/meson/gxbb-aoclk-32k.c b/drivers/clk/meson/gxbb-aoclk-32k.c
deleted file mode 100644 (file)
index 6804671..0000000
+++ /dev/null
@@ -1,193 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-/*
- * Copyright (c) 2017 BayLibre, SAS.
- * Author: Neil Armstrong <narmstrong@baylibre.com>
- */
-
-#include <linux/clk-provider.h>
-#include <linux/bitfield.h>
-#include <linux/regmap.h>
-#include "gxbb-aoclk.h"
-
-/*
- * The AO Domain embeds a dual/divider to generate a more precise
- * 32,768KHz clock for low-power suspend mode and CEC.
- *                      ______   ______
- *                     |      | |      |
- *         ______      | Div1 |-| Cnt1 |       ______
- *        |      |    /|______| |______|\     |      |
- * Xtal-->| Gate |---|  ______   ______  X-X--| Gate |-->
- *        |______| |  \|      | |      |/  |  |______|
- *                 |   | Div2 |-| Cnt2 |   |
- *                 |   |______| |______|   |
- *                 |_______________________|
- *
- * The dividing can be switched to single or dual, with a counter
- * for each divider to set when the switching is done.
- * The entire dividing mechanism can be also bypassed.
- */
-
-#define CLK_CNTL0_N1_MASK      GENMASK(11, 0)
-#define CLK_CNTL0_N2_MASK      GENMASK(23, 12)
-#define CLK_CNTL0_DUALDIV_EN   BIT(28)
-#define CLK_CNTL0_OUT_GATE_EN  BIT(30)
-#define CLK_CNTL0_IN_GATE_EN   BIT(31)
-
-#define CLK_CNTL1_M1_MASK      GENMASK(11, 0)
-#define CLK_CNTL1_M2_MASK      GENMASK(23, 12)
-#define CLK_CNTL1_BYPASS_EN    BIT(24)
-#define CLK_CNTL1_SELECT_OSC   BIT(27)
-
-#define PWR_CNTL_ALT_32K_SEL   GENMASK(13, 10)
-
-struct cec_32k_freq_table {
-       unsigned long parent_rate;
-       unsigned long target_rate;
-       bool dualdiv;
-       unsigned int n1;
-       unsigned int n2;
-       unsigned int m1;
-       unsigned int m2;
-};
-
-static const struct cec_32k_freq_table aoclk_cec_32k_table[] = {
-       [0] = {
-               .parent_rate = 24000000,
-               .target_rate = 32768,
-               .dualdiv = true,
-               .n1 = 733,
-               .n2 = 732,
-               .m1 = 8,
-               .m2 = 11,
-       },
-};
-
-/*
- * If CLK_CNTL0_DUALDIV_EN == 0
- *  - will use N1 divider only
- * If CLK_CNTL0_DUALDIV_EN == 1
- *  - hold M1 cycles of N1 divider then changes to N2
- *  - hold M2 cycles of N2 divider then changes to N1
- * Then we can get more accurate division.
- */
-static unsigned long aoclk_cec_32k_recalc_rate(struct clk_hw *hw,
-                                              unsigned long parent_rate)
-{
-       struct aoclk_cec_32k *cec_32k = to_aoclk_cec_32k(hw);
-       unsigned long n1;
-       u32 reg0, reg1;
-
-       regmap_read(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, &reg0);
-       regmap_read(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL1, &reg1);
-
-       if (reg1 & CLK_CNTL1_BYPASS_EN)
-               return parent_rate;
-
-       if (reg0 & CLK_CNTL0_DUALDIV_EN) {
-               unsigned long n2, m1, m2, f1, f2, p1, p2;
-
-               n1 = FIELD_GET(CLK_CNTL0_N1_MASK, reg0) + 1;
-               n2 = FIELD_GET(CLK_CNTL0_N2_MASK, reg0) + 1;
-
-               m1 = FIELD_GET(CLK_CNTL1_M1_MASK, reg1) + 1;
-               m2 = FIELD_GET(CLK_CNTL1_M2_MASK, reg1) + 1;
-
-               f1 = DIV_ROUND_CLOSEST(parent_rate, n1);
-               f2 = DIV_ROUND_CLOSEST(parent_rate, n2);
-
-               p1 = DIV_ROUND_CLOSEST(100000000 * m1, f1 * (m1 + m2));
-               p2 = DIV_ROUND_CLOSEST(100000000 * m2, f2 * (m1 + m2));
-
-               return DIV_ROUND_UP(100000000, p1 + p2);
-       }
-
-       n1 = FIELD_GET(CLK_CNTL0_N1_MASK, reg0) + 1;
-
-       return DIV_ROUND_CLOSEST(parent_rate, n1);
-}
-
-static const struct cec_32k_freq_table *find_cec_32k_freq(unsigned long rate,
-                                                         unsigned long prate)
-{
-       int i;
-
-       for (i = 0 ; i < ARRAY_SIZE(aoclk_cec_32k_table) ; ++i)
-               if (aoclk_cec_32k_table[i].parent_rate == prate &&
-                   aoclk_cec_32k_table[i].target_rate == rate)
-                       return &aoclk_cec_32k_table[i];
-
-       return NULL;
-}
-
-static long aoclk_cec_32k_round_rate(struct clk_hw *hw, unsigned long rate,
-                                    unsigned long *prate)
-{
-       const struct cec_32k_freq_table *freq = find_cec_32k_freq(rate,
-                                                                 *prate);
-
-       /* If invalid return first one */
-       if (!freq)
-               return aoclk_cec_32k_table[0].target_rate;
-
-       return freq->target_rate;
-}
-
-/*
- * From the Amlogic init procedure, the IN and OUT gates needs to be handled
- * in the init procedure to avoid any glitches.
- */
-
-static int aoclk_cec_32k_set_rate(struct clk_hw *hw, unsigned long rate,
-                                 unsigned long parent_rate)
-{
-       const struct cec_32k_freq_table *freq = find_cec_32k_freq(rate,
-                                                                 parent_rate);
-       struct aoclk_cec_32k *cec_32k = to_aoclk_cec_32k(hw);
-       u32 reg = 0;
-
-       if (!freq)
-               return -EINVAL;
-
-       /* Disable clock */
-       regmap_update_bits(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0,
-                          CLK_CNTL0_IN_GATE_EN | CLK_CNTL0_OUT_GATE_EN, 0);
-
-       reg = FIELD_PREP(CLK_CNTL0_N1_MASK, freq->n1 - 1);
-       if (freq->dualdiv)
-               reg |= CLK_CNTL0_DUALDIV_EN |
-                      FIELD_PREP(CLK_CNTL0_N2_MASK, freq->n2 - 1);
-
-       regmap_write(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0, reg);
-
-       reg = FIELD_PREP(CLK_CNTL1_M1_MASK, freq->m1 - 1);
-       if (freq->dualdiv)
-               reg |= FIELD_PREP(CLK_CNTL1_M2_MASK, freq->m2 - 1);
-
-       regmap_write(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL1, reg);
-
-       /* Enable clock */
-       regmap_update_bits(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0,
-                          CLK_CNTL0_IN_GATE_EN, CLK_CNTL0_IN_GATE_EN);
-
-       udelay(200);
-
-       regmap_update_bits(cec_32k->regmap, AO_RTC_ALT_CLK_CNTL0,
-                          CLK_CNTL0_OUT_GATE_EN, CLK_CNTL0_OUT_GATE_EN);
-
-       regmap_update_bits(cec_32k->regmap, AO_CRT_CLK_CNTL1,
-                          CLK_CNTL1_SELECT_OSC, CLK_CNTL1_SELECT_OSC);
-
-       /* Select 32k from XTAL */
-       regmap_update_bits(cec_32k->regmap,
-                         AO_RTI_PWR_CNTL_REG0,
-                         PWR_CNTL_ALT_32K_SEL,
-                         FIELD_PREP(PWR_CNTL_ALT_32K_SEL, 4));
-
-       return 0;
-}
-
-const struct clk_ops meson_aoclk_cec_32k_ops = {
-       .recalc_rate = aoclk_cec_32k_recalc_rate,
-       .round_rate = aoclk_cec_32k_round_rate,
-       .set_rate = aoclk_cec_32k_set_rate,
-};
index 42ed61d..449f6ac 100644 (file)
@@ -5,10 +5,23 @@
  */
 #include <linux/platform_device.h>
 #include <linux/mfd/syscon.h>
-#include "clk-regmap.h"
 #include "meson-aoclk.h"
 #include "gxbb-aoclk.h"
 
+#include "clk-regmap.h"
+#include "clk-dualdiv.h"
+
+#define IN_PREFIX "ao-in-"
+
+/* AO Configuration Clock registers offsets */
+#define AO_RTI_PWR_CNTL_REG1   0x0c
+#define AO_RTI_PWR_CNTL_REG0   0x10
+#define AO_RTI_GEN_CNTL_REG0   0x40
+#define AO_OSCIN_CNTL          0x58
+#define AO_CRT_CLK_CNTL1       0x68
+#define AO_RTC_ALT_CLK_CNTL0   0x94
+#define AO_RTC_ALT_CLK_CNTL1   0x98
+
 #define GXBB_AO_GATE(_name, _bit)                                      \
 static struct clk_regmap _name##_ao = {                                        \
        .data = &(struct clk_regmap_gate_data) {                        \
@@ -18,7 +31,7 @@ static struct clk_regmap _name##_ao = {                                       \
        .hw.init = &(struct clk_init_data) {                            \
                .name = #_name "_ao",                                   \
                .ops = &clk_regmap_gate_ops,                            \
-               .parent_names = (const char *[]){ "clk81" },            \
+               .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk" }, \
                .num_parents = 1,                                       \
                .flags = CLK_IGNORE_UNUSED,                             \
        },                                                              \
@@ -31,13 +44,174 @@ GXBB_AO_GATE(uart1, 3);
 GXBB_AO_GATE(uart2, 5);
 GXBB_AO_GATE(ir_blaster, 6);
 
-static struct aoclk_cec_32k cec_32k_ao = {
-       .hw.init = &(struct clk_init_data) {
-               .name = "cec_32k_ao",
-               .ops = &meson_aoclk_cec_32k_ops,
-               .parent_names = (const char *[]){ "xtal" },
+static struct clk_regmap ao_cts_oscin = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = AO_RTI_PWR_CNTL_REG0,
+               .bit_idx = 6,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "ao_cts_oscin",
+               .ops = &clk_regmap_gate_ro_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap ao_32k_pre = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = AO_RTC_ALT_CLK_CNTL0,
+               .bit_idx = 31,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "ao_32k_pre",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "ao_cts_oscin" },
+               .num_parents = 1,
+       },
+};
+
+static const struct meson_clk_dualdiv_param gxbb_32k_div_table[] = {
+       {
+               .dual   = 1,
+               .n1     = 733,
+               .m1     = 8,
+               .n2     = 732,
+               .m2     = 11,
+       }, {}
+};
+
+static struct clk_regmap ao_32k_div = {
+       .data = &(struct meson_clk_dualdiv_data){
+               .n1 = {
+                       .reg_off = AO_RTC_ALT_CLK_CNTL0,
+                       .shift   = 0,
+                       .width   = 12,
+               },
+               .n2 = {
+                       .reg_off = AO_RTC_ALT_CLK_CNTL0,
+                       .shift   = 12,
+                       .width   = 12,
+               },
+               .m1 = {
+                       .reg_off = AO_RTC_ALT_CLK_CNTL1,
+                       .shift   = 0,
+                       .width   = 12,
+               },
+               .m2 = {
+                       .reg_off = AO_RTC_ALT_CLK_CNTL1,
+                       .shift   = 12,
+                       .width   = 12,
+               },
+               .dual = {
+                       .reg_off = AO_RTC_ALT_CLK_CNTL0,
+                       .shift   = 28,
+                       .width   = 1,
+               },
+               .table = gxbb_32k_div_table,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "ao_32k_div",
+               .ops = &meson_clk_dualdiv_ops,
+               .parent_names = (const char *[]){ "ao_32k_pre" },
+               .num_parents = 1,
+       },
+};
+
+static struct clk_regmap ao_32k_sel = {
+       .data = &(struct clk_regmap_mux_data) {
+               .offset = AO_RTC_ALT_CLK_CNTL1,
+               .mask = 0x1,
+               .shift = 24,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "ao_32k_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = (const char *[]){ "ao_32k_div",
+                                                 "ao_32k_pre" },
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap ao_32k = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = AO_RTC_ALT_CLK_CNTL0,
+               .bit_idx = 30,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "ao_32k",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "ao_32k_sel" },
                .num_parents = 1,
-               .flags = CLK_IGNORE_UNUSED,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap ao_cts_rtc_oscin = {
+       .data = &(struct clk_regmap_mux_data) {
+               .offset = AO_RTI_PWR_CNTL_REG0,
+               .mask = 0x7,
+               .shift = 10,
+               .table = (u32[]){ 1, 2, 3, 4 },
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "ao_cts_rtc_oscin",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "ext-32k-0",
+                                                 IN_PREFIX "ext-32k-1",
+                                                 IN_PREFIX "ext-32k-2",
+                                                 "ao_32k" },
+               .num_parents = 4,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap ao_clk81 = {
+       .data = &(struct clk_regmap_mux_data) {
+               .offset = AO_RTI_PWR_CNTL_REG0,
+               .mask = 0x1,
+               .shift = 0,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "ao_clk81",
+               .ops = &clk_regmap_mux_ro_ops,
+               .parent_names = (const char *[]){ IN_PREFIX "mpeg-clk",
+                                                 "ao_cts_rtc_oscin" },
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap ao_cts_cec = {
+       .data = &(struct clk_regmap_mux_data) {
+               .offset = AO_CRT_CLK_CNTL1,
+               .mask = 0x1,
+               .shift = 27,
+               .flags = CLK_MUX_ROUND_CLOSEST,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "ao_cts_cec",
+               .ops = &clk_regmap_mux_ops,
+               /*
+                * FIXME: The 'fixme' parent obviously does not exist.
+                *
+                * ATM, CCF won't call get_parent() if num_parents is 1. It
+                * does not allow NULL as a parent name either.
+                *
+                * On this particular mux, we only know the input #1 parent
+                * but, on boot, unknown input #0 is set, so it is critical
+                * to call .get_parent() on it
+                *
+                * Until CCF gets fixed, adding this fake parent that won't
+                * ever be registered should work around the problem
+                */
+               .parent_names = (const char *[]){ "fixme",
+                                                 "ao_cts_rtc_oscin" },
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_PARENT,
        },
 };
 
@@ -50,13 +224,21 @@ static const unsigned int gxbb_aoclk_reset[] = {
        [RESET_AO_IR_BLASTER] = 23,
 };
 
-static struct clk_regmap *gxbb_aoclk_gate[] = {
-       [CLKID_AO_REMOTE] = &remote_ao,
-       [CLKID_AO_I2C_MASTER] = &i2c_master_ao,
-       [CLKID_AO_I2C_SLAVE] = &i2c_slave_ao,
-       [CLKID_AO_UART1] = &uart1_ao,
-       [CLKID_AO_UART2] = &uart2_ao,
-       [CLKID_AO_IR_BLASTER] = &ir_blaster_ao,
+static struct clk_regmap *gxbb_aoclk[] = {
+       &remote_ao,
+       &i2c_master_ao,
+       &i2c_slave_ao,
+       &uart1_ao,
+       &uart2_ao,
+       &ir_blaster_ao,
+       &ao_cts_oscin,
+       &ao_32k_pre,
+       &ao_32k_div,
+       &ao_32k_sel,
+       &ao_32k,
+       &ao_cts_rtc_oscin,
+       &ao_clk81,
+       &ao_cts_cec,
 };
 
 static const struct clk_hw_onecell_data gxbb_aoclk_onecell_data = {
@@ -67,52 +249,38 @@ static const struct clk_hw_onecell_data gxbb_aoclk_onecell_data = {
                [CLKID_AO_UART1] = &uart1_ao.hw,
                [CLKID_AO_UART2] = &uart2_ao.hw,
                [CLKID_AO_IR_BLASTER] = &ir_blaster_ao.hw,
-               [CLKID_AO_CEC_32K] = &cec_32k_ao.hw,
+               [CLKID_AO_CEC_32K] = &ao_cts_cec.hw,
+               [CLKID_AO_CTS_OSCIN] = &ao_cts_oscin.hw,
+               [CLKID_AO_32K_PRE] = &ao_32k_pre.hw,
+               [CLKID_AO_32K_DIV] = &ao_32k_div.hw,
+               [CLKID_AO_32K_SEL] = &ao_32k_sel.hw,
+               [CLKID_AO_32K] = &ao_32k.hw,
+               [CLKID_AO_CTS_RTC_OSCIN] = &ao_cts_rtc_oscin.hw,
+               [CLKID_AO_CLK81] = &ao_clk81.hw,
        },
        .num = NR_CLKS,
 };
 
-static int gxbb_register_cec_ao_32k(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct regmap *regmap;
-       int ret;
-
-       regmap = syscon_node_to_regmap(of_get_parent(dev->of_node));
-       if (IS_ERR(regmap)) {
-               dev_err(dev, "failed to get regmap\n");
-               return PTR_ERR(regmap);
-       }
-
-       /* Specific clocks */
-       cec_32k_ao.regmap = regmap;
-       ret = devm_clk_hw_register(dev, &cec_32k_ao.hw);
-       if (ret) {
-               dev_err(&pdev->dev, "clk cec_32k_ao register failed.\n");
-               return ret;
-       }
-
-       return 0;
-}
+static const struct meson_aoclk_input gxbb_aoclk_inputs[] = {
+       { .name = "xtal",       .required = true,  },
+       { .name = "mpeg-clk",   .required = true,  },
+       {. name = "ext-32k-0",  .required = false, },
+       {. name = "ext-32k-1",  .required = false, },
+       {. name = "ext-32k-2",  .required = false, },
+};
 
 static const struct meson_aoclk_data gxbb_aoclkc_data = {
        .reset_reg      = AO_RTI_GEN_CNTL_REG0,
        .num_reset      = ARRAY_SIZE(gxbb_aoclk_reset),
        .reset          = gxbb_aoclk_reset,
-       .num_clks       = ARRAY_SIZE(gxbb_aoclk_gate),
-       .clks           = gxbb_aoclk_gate,
+       .num_clks       = ARRAY_SIZE(gxbb_aoclk),
+       .clks           = gxbb_aoclk,
        .hw_data        = &gxbb_aoclk_onecell_data,
+       .inputs         = gxbb_aoclk_inputs,
+       .num_inputs     = ARRAY_SIZE(gxbb_aoclk_inputs),
+       .input_prefix   = IN_PREFIX,
 };
 
-static int gxbb_aoclkc_probe(struct platform_device *pdev)
-{
-       int ret = gxbb_register_cec_ao_32k(pdev);
-       if (ret)
-               return ret;
-
-       return meson_aoclkc_probe(pdev);
-}
-
 static const struct of_device_id gxbb_aoclkc_match_table[] = {
        {
                .compatible     = "amlogic,meson-gx-aoclkc",
@@ -122,7 +290,7 @@ static const struct of_device_id gxbb_aoclkc_match_table[] = {
 };
 
 static struct platform_driver gxbb_aoclkc_driver = {
-       .probe          = gxbb_aoclkc_probe,
+       .probe          = meson_aoclkc_probe,
        .driver         = {
                .name   = "gxbb-aoclkc",
                .of_match_table = gxbb_aoclkc_match_table,
index c514493..1db16f9 100644 (file)
@@ -7,25 +7,7 @@
 #ifndef __GXBB_AOCLKC_H
 #define __GXBB_AOCLKC_H
 
-#define NR_CLKS        7
-
-/* AO Configuration Clock registers offsets */
-#define AO_RTI_PWR_CNTL_REG1   0x0c
-#define AO_RTI_PWR_CNTL_REG0   0x10
-#define AO_RTI_GEN_CNTL_REG0   0x40
-#define AO_OSCIN_CNTL          0x58
-#define AO_CRT_CLK_CNTL1       0x68
-#define AO_RTC_ALT_CLK_CNTL0   0x94
-#define AO_RTC_ALT_CLK_CNTL1   0x98
-
-struct aoclk_cec_32k {
-       struct clk_hw hw;
-       struct regmap *regmap;
-};
-
-#define to_aoclk_cec_32k(_hw) container_of(_hw, struct aoclk_cec_32k, hw)
-
-extern const struct clk_ops meson_aoclk_cec_32k_ops;
+#define NR_CLKS        14
 
 #include <dt-bindings/clock/gxbb-aoclkc.h>
 #include <dt-bindings/reset/gxbb-aoclkc.h>
index 65f2599..04df2e2 100644 (file)
@@ -4,17 +4,20 @@
  * Michael Turquette <mturquette@baylibre.com>
  */
 
-#include <linux/clk.h>
 #include <linux/clk-provider.h>
 #include <linux/init.h>
 #include <linux/of_device.h>
-#include <linux/mfd/syscon.h>
 #include <linux/platform_device.h>
-#include <linux/regmap.h>
 
-#include "clkc.h"
 #include "gxbb.h"
+#include "clk-input.h"
 #include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-mpll.h"
+#include "meson-eeclk.h"
+#include "vid-pll-div.h"
+
+#define IN_PREFIX "ee-in-"
 
 static DEFINE_SPINLOCK(meson_clk_lock);
 
@@ -118,7 +121,7 @@ static struct clk_regmap gxbb_fixed_pll_dco = {
        .hw.init = &(struct clk_init_data){
                .name = "fixed_pll_dco",
                .ops = &meson_clk_pll_ro_ops,
-               .parent_names = (const char *[]){ "xtal" },
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
                .num_parents = 1,
        },
 };
@@ -148,7 +151,7 @@ static struct clk_fixed_factor gxbb_hdmi_pll_pre_mult = {
        .hw.init = &(struct clk_init_data){
                .name = "hdmi_pll_pre_mult",
                .ops = &clk_fixed_factor_ops,
-               .parent_names = (const char *[]){ "xtal" },
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
                .num_parents = 1,
        },
 };
@@ -241,7 +244,7 @@ static struct clk_regmap gxl_hdmi_pll_dco = {
        .hw.init = &(struct clk_init_data){
                .name = "hdmi_pll_dco",
                .ops = &meson_clk_pll_ro_ops,
-               .parent_names = (const char *[]){ "xtal" },
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
                .num_parents = 1,
                /*
                 * Display directly handle hdmi pll registers ATM, we need
@@ -378,7 +381,7 @@ static struct clk_regmap gxbb_sys_pll_dco = {
        .hw.init = &(struct clk_init_data){
                .name = "sys_pll_dco",
                .ops = &meson_clk_pll_ro_ops,
-               .parent_names = (const char *[]){ "xtal" },
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
                .num_parents = 1,
        },
 };
@@ -439,7 +442,7 @@ static struct clk_regmap gxbb_gp0_pll_dco = {
        .hw.init = &(struct clk_init_data){
                .name = "gp0_pll_dco",
                .ops = &meson_clk_pll_ops,
-               .parent_names = (const char *[]){ "xtal" },
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
                .num_parents = 1,
        },
 };
@@ -491,7 +494,7 @@ static struct clk_regmap gxl_gp0_pll_dco = {
        .hw.init = &(struct clk_init_data){
                .name = "gp0_pll_dco",
                .ops = &meson_clk_pll_ops,
-               .parent_names = (const char *[]){ "xtal" },
+               .parent_names = (const char *[]){ IN_PREFIX "xtal" },
                .num_parents = 1,
        },
 };
@@ -789,7 +792,7 @@ static struct clk_regmap gxbb_mpll2 = {
 
 static u32 mux_table_clk81[]   = { 0, 2, 3, 4, 5, 6, 7 };
 static const char * const clk81_parent_names[] = {
-       "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
+       IN_PREFIX "xtal", "fclk_div7", "mpll1", "mpll2", "fclk_div4",
        "fclk_div3", "fclk_div5"
 };
 
@@ -852,7 +855,7 @@ static struct clk_regmap gxbb_sar_adc_clk_sel = {
                .name = "sar_adc_clk_sel",
                .ops = &clk_regmap_mux_ops,
                /* NOTE: The datasheet doesn't list the parents for bit 10 */
-               .parent_names = (const char *[]){ "xtal", "clk81", },
+               .parent_names = (const char *[]){ IN_PREFIX "xtal", "clk81", },
                .num_parents = 2,
        },
 };
@@ -891,7 +894,7 @@ static struct clk_regmap gxbb_sar_adc_clk = {
  */
 
 static const char * const gxbb_mali_0_1_parent_names[] = {
-       "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7",
+       IN_PREFIX "xtal", "gp0_pll", "mpll2", "mpll1", "fclk_div7",
        "fclk_div4", "fclk_div3", "fclk_div5"
 };
 
@@ -1153,7 +1156,7 @@ static struct clk_regmap gxbb_32k_clk = {
 };
 
 static const char * const gxbb_32k_clk_parent_names[] = {
-       "xtal", "cts_slow_oscin", "fclk_div3", "fclk_div5"
+       IN_PREFIX "xtal", "cts_slow_oscin", "fclk_div3", "fclk_div5"
 };
 
 static struct clk_regmap gxbb_32k_clk_sel = {
@@ -1172,7 +1175,7 @@ static struct clk_regmap gxbb_32k_clk_sel = {
 };
 
 static const char * const gxbb_sd_emmc_clk0_parent_names[] = {
-       "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7",
+       IN_PREFIX "xtal", "fclk_div2", "fclk_div3", "fclk_div5", "fclk_div7",
 
        /*
         * Following these parent clocks, we should also have had mpll2, mpll3
@@ -2138,7 +2141,7 @@ static struct clk_regmap gxbb_hdmi_tx = {
 /* HDMI Clocks */
 
 static const char * const gxbb_hdmi_parent_names[] = {
-       "xtal", "fclk_div4", "fclk_div3", "fclk_div5"
+       IN_PREFIX "xtal", "fclk_div4", "fclk_div3", "fclk_div5"
 };
 
 static struct clk_regmap gxbb_hdmi_sel = {
@@ -2285,7 +2288,7 @@ static struct clk_regmap gxbb_vdec_hevc = {
 static u32 mux_table_gen_clk[] = { 0, 4, 5, 6, 7, 8,
                                    9, 10, 11, 13, 14, };
 static const char * const gen_clk_parent_names[] = {
-       "xtal", "vdec_1", "vdec_hevc", "mpll0", "mpll1", "mpll2",
+       IN_PREFIX "xtal", "vdec_1", "vdec_hevc", "mpll0", "mpll1", "mpll2",
        "fclk_div4", "fclk_div3", "fclk_div5", "fclk_div7", "gp0_pll",
 };
 
@@ -2854,6 +2857,192 @@ static struct clk_hw_onecell_data gxl_hw_onecell_data = {
 };
 
 static struct clk_regmap *const gxbb_clk_regmaps[] = {
+       &gxbb_clk81,
+       &gxbb_ddr,
+       &gxbb_dos,
+       &gxbb_isa,
+       &gxbb_pl301,
+       &gxbb_periphs,
+       &gxbb_spicc,
+       &gxbb_i2c,
+       &gxbb_sar_adc,
+       &gxbb_smart_card,
+       &gxbb_rng0,
+       &gxbb_uart0,
+       &gxbb_sdhc,
+       &gxbb_stream,
+       &gxbb_async_fifo,
+       &gxbb_sdio,
+       &gxbb_abuf,
+       &gxbb_hiu_iface,
+       &gxbb_assist_misc,
+       &gxbb_spi,
+       &gxbb_i2s_spdif,
+       &gxbb_eth,
+       &gxbb_demux,
+       &gxbb_aiu_glue,
+       &gxbb_iec958,
+       &gxbb_i2s_out,
+       &gxbb_amclk,
+       &gxbb_aififo2,
+       &gxbb_mixer,
+       &gxbb_mixer_iface,
+       &gxbb_adc,
+       &gxbb_blkmv,
+       &gxbb_aiu,
+       &gxbb_uart1,
+       &gxbb_g2d,
+       &gxbb_usb0,
+       &gxbb_usb1,
+       &gxbb_reset,
+       &gxbb_nand,
+       &gxbb_dos_parser,
+       &gxbb_usb,
+       &gxbb_vdin1,
+       &gxbb_ahb_arb0,
+       &gxbb_efuse,
+       &gxbb_boot_rom,
+       &gxbb_ahb_data_bus,
+       &gxbb_ahb_ctrl_bus,
+       &gxbb_hdmi_intr_sync,
+       &gxbb_hdmi_pclk,
+       &gxbb_usb1_ddr_bridge,
+       &gxbb_usb0_ddr_bridge,
+       &gxbb_mmc_pclk,
+       &gxbb_dvin,
+       &gxbb_uart2,
+       &gxbb_sana,
+       &gxbb_vpu_intr,
+       &gxbb_sec_ahb_ahb3_bridge,
+       &gxbb_clk81_a53,
+       &gxbb_vclk2_venci0,
+       &gxbb_vclk2_venci1,
+       &gxbb_vclk2_vencp0,
+       &gxbb_vclk2_vencp1,
+       &gxbb_gclk_venci_int0,
+       &gxbb_gclk_vencp_int,
+       &gxbb_dac_clk,
+       &gxbb_aoclk_gate,
+       &gxbb_iec958_gate,
+       &gxbb_enc480p,
+       &gxbb_rng1,
+       &gxbb_gclk_venci_int1,
+       &gxbb_vclk2_venclmcc,
+       &gxbb_vclk2_vencl,
+       &gxbb_vclk_other,
+       &gxbb_edp,
+       &gxbb_ao_media_cpu,
+       &gxbb_ao_ahb_sram,
+       &gxbb_ao_ahb_bus,
+       &gxbb_ao_iface,
+       &gxbb_ao_i2c,
+       &gxbb_emmc_a,
+       &gxbb_emmc_b,
+       &gxbb_emmc_c,
+       &gxbb_sar_adc_clk,
+       &gxbb_mali_0,
+       &gxbb_mali_1,
+       &gxbb_cts_amclk,
+       &gxbb_cts_mclk_i958,
+       &gxbb_32k_clk,
+       &gxbb_sd_emmc_a_clk0,
+       &gxbb_sd_emmc_b_clk0,
+       &gxbb_sd_emmc_c_clk0,
+       &gxbb_vpu_0,
+       &gxbb_vpu_1,
+       &gxbb_vapb_0,
+       &gxbb_vapb_1,
+       &gxbb_vapb,
+       &gxbb_mpeg_clk_div,
+       &gxbb_sar_adc_clk_div,
+       &gxbb_mali_0_div,
+       &gxbb_mali_1_div,
+       &gxbb_cts_mclk_i958_div,
+       &gxbb_32k_clk_div,
+       &gxbb_sd_emmc_a_clk0_div,
+       &gxbb_sd_emmc_b_clk0_div,
+       &gxbb_sd_emmc_c_clk0_div,
+       &gxbb_vpu_0_div,
+       &gxbb_vpu_1_div,
+       &gxbb_vapb_0_div,
+       &gxbb_vapb_1_div,
+       &gxbb_mpeg_clk_sel,
+       &gxbb_sar_adc_clk_sel,
+       &gxbb_mali_0_sel,
+       &gxbb_mali_1_sel,
+       &gxbb_mali,
+       &gxbb_cts_amclk_sel,
+       &gxbb_cts_mclk_i958_sel,
+       &gxbb_cts_i958,
+       &gxbb_32k_clk_sel,
+       &gxbb_sd_emmc_a_clk0_sel,
+       &gxbb_sd_emmc_b_clk0_sel,
+       &gxbb_sd_emmc_c_clk0_sel,
+       &gxbb_vpu_0_sel,
+       &gxbb_vpu_1_sel,
+       &gxbb_vpu,
+       &gxbb_vapb_0_sel,
+       &gxbb_vapb_1_sel,
+       &gxbb_vapb_sel,
+       &gxbb_mpll0,
+       &gxbb_mpll1,
+       &gxbb_mpll2,
+       &gxbb_mpll0_div,
+       &gxbb_mpll1_div,
+       &gxbb_mpll2_div,
+       &gxbb_cts_amclk_div,
+       &gxbb_fixed_pll,
+       &gxbb_sys_pll,
+       &gxbb_mpll_prediv,
+       &gxbb_fclk_div2,
+       &gxbb_fclk_div3,
+       &gxbb_fclk_div4,
+       &gxbb_fclk_div5,
+       &gxbb_fclk_div7,
+       &gxbb_vdec_1_sel,
+       &gxbb_vdec_1_div,
+       &gxbb_vdec_1,
+       &gxbb_vdec_hevc_sel,
+       &gxbb_vdec_hevc_div,
+       &gxbb_vdec_hevc,
+       &gxbb_gen_clk_sel,
+       &gxbb_gen_clk_div,
+       &gxbb_gen_clk,
+       &gxbb_fixed_pll_dco,
+       &gxbb_sys_pll_dco,
+       &gxbb_gp0_pll,
+       &gxbb_vid_pll,
+       &gxbb_vid_pll_sel,
+       &gxbb_vid_pll_div,
+       &gxbb_vclk,
+       &gxbb_vclk_sel,
+       &gxbb_vclk_div,
+       &gxbb_vclk_input,
+       &gxbb_vclk_div1,
+       &gxbb_vclk_div2_en,
+       &gxbb_vclk_div4_en,
+       &gxbb_vclk_div6_en,
+       &gxbb_vclk_div12_en,
+       &gxbb_vclk2,
+       &gxbb_vclk2_sel,
+       &gxbb_vclk2_div,
+       &gxbb_vclk2_input,
+       &gxbb_vclk2_div1,
+       &gxbb_vclk2_div2_en,
+       &gxbb_vclk2_div4_en,
+       &gxbb_vclk2_div6_en,
+       &gxbb_vclk2_div12_en,
+       &gxbb_cts_enci,
+       &gxbb_cts_enci_sel,
+       &gxbb_cts_encp,
+       &gxbb_cts_encp_sel,
+       &gxbb_cts_vdac,
+       &gxbb_cts_vdac_sel,
+       &gxbb_hdmi_tx,
+       &gxbb_hdmi_tx_sel,
+       &gxbb_hdmi_sel,
+       &gxbb_hdmi_div,
+       &gxbb_hdmi,
        &gxbb_gp0_pll_dco,
        &gxbb_hdmi_pll,
        &gxbb_hdmi_pll_od,
@@ -2862,14 +3051,6 @@ static struct clk_regmap *const gxbb_clk_regmaps[] = {
 };
 
 static struct clk_regmap *const gxl_clk_regmaps[] = {
-       &gxl_gp0_pll_dco,
-       &gxl_hdmi_pll,
-       &gxl_hdmi_pll_od,
-       &gxl_hdmi_pll_od2,
-       &gxl_hdmi_pll_dco,
-};
-
-static struct clk_regmap *const gx_clk_regmaps[] = {
        &gxbb_clk81,
        &gxbb_ddr,
        &gxbb_dos,
@@ -3056,23 +3237,22 @@ static struct clk_regmap *const gx_clk_regmaps[] = {
        &gxbb_hdmi_sel,
        &gxbb_hdmi_div,
        &gxbb_hdmi,
+       &gxl_gp0_pll_dco,
+       &gxl_hdmi_pll,
+       &gxl_hdmi_pll_od,
+       &gxl_hdmi_pll_od2,
+       &gxl_hdmi_pll_dco,
 };
 
-struct clkc_data {
-       struct clk_regmap *const *regmap_clks;
-       unsigned int regmap_clks_count;
-       struct clk_hw_onecell_data *hw_onecell_data;
-};
-
-static const struct clkc_data gxbb_clkc_data = {
+static const struct meson_eeclkc_data gxbb_clkc_data = {
        .regmap_clks = gxbb_clk_regmaps,
-       .regmap_clks_count = ARRAY_SIZE(gxbb_clk_regmaps),
+       .regmap_clk_num = ARRAY_SIZE(gxbb_clk_regmaps),
        .hw_onecell_data = &gxbb_hw_onecell_data,
 };
 
-static const struct clkc_data gxl_clkc_data = {
+static const struct meson_eeclkc_data gxl_clkc_data = {
        .regmap_clks = gxl_clk_regmaps,
-       .regmap_clks_count = ARRAY_SIZE(gxl_clk_regmaps),
+       .regmap_clk_num = ARRAY_SIZE(gxl_clk_regmaps),
        .hw_onecell_data = &gxl_hw_onecell_data,
 };
 
@@ -3082,52 +3262,8 @@ static const struct of_device_id clkc_match_table[] = {
        {},
 };
 
-static int gxbb_clkc_probe(struct platform_device *pdev)
-{
-       const struct clkc_data *clkc_data;
-       struct regmap *map;
-       int ret, i;
-       struct device *dev = &pdev->dev;
-
-       clkc_data = of_device_get_match_data(dev);
-       if (!clkc_data)
-               return -EINVAL;
-
-       /* Get the hhi system controller node if available */
-       map = syscon_node_to_regmap(of_get_parent(dev->of_node));
-       if (IS_ERR(map)) {
-               dev_err(dev, "failed to get HHI regmap\n");
-               return PTR_ERR(map);
-       }
-
-       /* Populate regmap for the common regmap backed clocks */
-       for (i = 0; i < ARRAY_SIZE(gx_clk_regmaps); i++)
-               gx_clk_regmaps[i]->map = map;
-
-       /* Populate regmap for soc specific clocks */
-       for (i = 0; i < clkc_data->regmap_clks_count; i++)
-               clkc_data->regmap_clks[i]->map = map;
-
-       /* Register all clks */
-       for (i = 0; i < clkc_data->hw_onecell_data->num; i++) {
-               /* array might be sparse */
-               if (!clkc_data->hw_onecell_data->hws[i])
-                       continue;
-
-               ret = devm_clk_hw_register(dev,
-                                          clkc_data->hw_onecell_data->hws[i]);
-               if (ret) {
-                       dev_err(dev, "Clock registration failed\n");
-                       return ret;
-               }
-       }
-
-       return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
-                                          clkc_data->hw_onecell_data);
-}
-
 static struct platform_driver gxbb_driver = {
-       .probe          = gxbb_clkc_probe,
+       .probe          = meson_eeclkc_probe,
        .driver         = {
                .name   = "gxbb-clkc",
                .of_match_table = clkc_match_table,
index f965845..b679519 100644 (file)
 #include <linux/reset-controller.h>
 #include <linux/mfd/syscon.h>
 #include <linux/of_device.h>
-#include "clk-regmap.h"
+#include <linux/slab.h>
 #include "meson-aoclk.h"
 
+#include "clk-input.h"
+
 static int meson_aoclk_do_reset(struct reset_controller_dev *rcdev,
                               unsigned long id)
 {
@@ -31,6 +33,37 @@ static const struct reset_control_ops meson_aoclk_reset_ops = {
        .reset = meson_aoclk_do_reset,
 };
 
+static int meson_aoclkc_register_inputs(struct device *dev,
+                                       struct meson_aoclk_data *data)
+{
+       struct clk_hw *hw;
+       char *str;
+       int i;
+
+       for (i = 0; i < data->num_inputs; i++) {
+               const struct meson_aoclk_input *in = &data->inputs[i];
+
+               str = kasprintf(GFP_KERNEL, "%s%s", data->input_prefix,
+                               in->name);
+               if (!str)
+                       return -ENOMEM;
+
+               hw = meson_clk_hw_register_input(dev, in->name, str, 0);
+               kfree(str);
+
+               if (IS_ERR(hw)) {
+                       if (!in->required && PTR_ERR(hw) == -ENOENT)
+                               continue;
+                       else if (PTR_ERR(hw) != -EPROBE_DEFER)
+                               dev_err(dev, "failed to register input %s\n",
+                                       in->name);
+                       return PTR_ERR(hw);
+               }
+       }
+
+       return 0;
+}
+
 int meson_aoclkc_probe(struct platform_device *pdev)
 {
        struct meson_aoclk_reset_controller *rstc;
@@ -53,6 +86,10 @@ int meson_aoclkc_probe(struct platform_device *pdev)
                return PTR_ERR(regmap);
        }
 
+       ret = meson_aoclkc_register_inputs(dev, data);
+       if (ret)
+               return ret;
+
        /* Reset Controller */
        rstc->data = data;
        rstc->regmap = regmap;
@@ -65,15 +102,20 @@ int meson_aoclkc_probe(struct platform_device *pdev)
                return ret;
        }
 
-       /*
-        * Populate regmap and register all clks
-        */
-       for (clkid = 0; clkid < data->num_clks; clkid++) {
+       /* Populate regmap */
+       for (clkid = 0; clkid < data->num_clks; clkid++)
                data->clks[clkid]->map = regmap;
 
+       /* Register all clks */
+       for (clkid = 0; clkid < data->hw_data->num; clkid++) {
+               if (!data->hw_data->hws[clkid])
+                       continue;
+
                ret = devm_clk_hw_register(dev, data->hw_data->hws[clkid]);
-               if (ret)
+               if (ret) {
+                       dev_err(dev, "Clock registration failed\n");
                        return ret;
+               }
        }
 
        return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
index ab2819e..999cde3 100644 (file)
 #ifndef __MESON_AOCLK_H__
 #define __MESON_AOCLK_H__
 
+#include <linux/clk-provider.h>
 #include <linux/platform_device.h>
+#include <linux/regmap.h>
 #include <linux/reset-controller.h>
+
 #include "clk-regmap.h"
 
+struct meson_aoclk_input {
+       const char *name;
+       bool required;
+};
+
 struct meson_aoclk_data {
        const unsigned int                      reset_reg;
        const int                               num_reset;
        const unsigned int                      *reset;
-       int                                     num_clks;
+       const int                               num_clks;
        struct clk_regmap                       **clks;
+       const int                               num_inputs;
+       const struct meson_aoclk_input          *inputs;
+       const char                              *input_prefix;
        const struct clk_hw_onecell_data        *hw_data;
 };
 
diff --git a/drivers/clk/meson/meson-eeclk.c b/drivers/clk/meson/meson-eeclk.c
new file mode 100644 (file)
index 0000000..37a34c9
--- /dev/null
@@ -0,0 +1,63 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+#include <linux/clk-provider.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
+
+#include "clk-input.h"
+#include "clk-regmap.h"
+#include "meson-eeclk.h"
+
+int meson_eeclkc_probe(struct platform_device *pdev)
+{
+       const struct meson_eeclkc_data *data;
+       struct device *dev = &pdev->dev;
+       struct clk_hw *input;
+       struct regmap *map;
+       int ret, i;
+
+       data = of_device_get_match_data(dev);
+       if (!data)
+               return -EINVAL;
+
+       /* Get the hhi system controller node */
+       map = syscon_node_to_regmap(of_get_parent(dev->of_node));
+       if (IS_ERR(map)) {
+               dev_err(dev,
+                       "failed to get HHI regmap\n");
+               return PTR_ERR(map);
+       }
+
+       input = meson_clk_hw_register_input(dev, "xtal", IN_PREFIX "xtal", 0);
+       if (IS_ERR(input)) {
+               ret = PTR_ERR(input);
+               if (ret != -EPROBE_DEFER)
+                       dev_err(dev, "failed to get input clock");
+               return ret;
+       }
+
+       /* Populate regmap for the regmap backed clocks */
+       for (i = 0; i < data->regmap_clk_num; i++)
+               data->regmap_clks[i]->map = map;
+
+       for (i = 0; i < data->hw_onecell_data->num; i++) {
+               /* array might be sparse */
+               if (!data->hw_onecell_data->hws[i])
+                       continue;
+
+               ret = devm_clk_hw_register(dev, data->hw_onecell_data->hws[i]);
+               if (ret) {
+                       dev_err(dev, "Clock registration failed\n");
+                       return ret;
+               }
+       }
+
+       return devm_of_clk_add_hw_provider(dev, of_clk_hw_onecell_get,
+                                          data->hw_onecell_data);
+}
diff --git a/drivers/clk/meson/meson-eeclk.h b/drivers/clk/meson/meson-eeclk.h
new file mode 100644 (file)
index 0000000..1b809b1
--- /dev/null
@@ -0,0 +1,25 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+#ifndef __MESON_CLKC_H
+#define __MESON_CLKC_H
+
+#include <linux/clk-provider.h>
+#include "clk-regmap.h"
+
+#define IN_PREFIX "ee-in-"
+
+struct platform_device;
+
+struct meson_eeclkc_data {
+       struct clk_regmap *const        *regmap_clks;
+       unsigned int                    regmap_clk_num;
+       struct clk_hw_onecell_data      *hw_onecell_data;
+};
+
+int meson_eeclkc_probe(struct platform_device *pdev);
+
+#endif /* __MESON_CLKC_H */
index 950d0e5..576ad42 100644 (file)
 #include <linux/slab.h>
 #include <linux/regmap.h>
 
-#include "clkc.h"
 #include "meson8b.h"
 #include "clk-regmap.h"
+#include "clk-pll.h"
+#include "clk-mpll.h"
 
 static DEFINE_SPINLOCK(meson_clk_lock);
 
@@ -803,16 +804,16 @@ static struct clk_fixed_factor meson8b_cpu_clk_div8 = {
        },
 };
 
-static u32 mux_table_abp[] = { 1, 2, 3, 4, 5, 6, 7 };
-static struct clk_regmap meson8b_abp_clk_sel = {
+static u32 mux_table_apb[] = { 1, 2, 3, 4, 5, 6, 7 };
+static struct clk_regmap meson8b_apb_clk_sel = {
        .data = &(struct clk_regmap_mux_data){
                .offset = HHI_SYS_CPU_CLK_CNTL1,
                .mask = 0x7,
                .shift = 3,
-               .table = mux_table_abp,
+               .table = mux_table_apb,
        },
        .hw.init = &(struct clk_init_data){
-               .name = "abp_clk_sel",
+               .name = "apb_clk_sel",
                .ops = &clk_regmap_mux_ops,
                .parent_names = (const char *[]){ "cpu_clk_div2",
                                                  "cpu_clk_div3",
@@ -825,16 +826,16 @@ static struct clk_regmap meson8b_abp_clk_sel = {
        },
 };
 
-static struct clk_regmap meson8b_abp_clk_gate = {
+static struct clk_regmap meson8b_apb_clk_gate = {
        .data = &(struct clk_regmap_gate_data){
                .offset = HHI_SYS_CPU_CLK_CNTL1,
                .bit_idx = 16,
                .flags = CLK_GATE_SET_TO_DISABLE,
        },
        .hw.init = &(struct clk_init_data){
-               .name = "abp_clk_dis",
+               .name = "apb_clk_dis",
                .ops = &clk_regmap_gate_ro_ops,
-               .parent_names = (const char *[]){ "abp_clk_sel" },
+               .parent_names = (const char *[]){ "apb_clk_sel" },
                .num_parents = 1,
                .flags = CLK_SET_RATE_PARENT,
        },
@@ -1573,6 +1574,135 @@ static struct clk_regmap meson8b_hdmi_sys = {
        },
 };
 
+/*
+ * The MALI IP is clocked by two identical clocks (mali_0 and mali_1)
+ * muxed by a glitch-free switch on Meson8b and Meson8m2. Meson8 only
+ * has mali_0 and no glitch-free mux.
+ */
+static const char * const meson8b_mali_0_1_parent_names[] = {
+       "xtal", "mpll2", "mpll1", "fclk_div7", "fclk_div4", "fclk_div3",
+       "fclk_div5"
+};
+
+static u32 meson8b_mali_0_1_mux_table[] = { 0, 2, 3, 4, 5, 6, 7 };
+
+static struct clk_regmap meson8b_mali_0_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 9,
+               .table = meson8b_mali_0_1_mux_table,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_0_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = meson8b_mali_0_1_parent_names,
+               .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_names),
+               /*
+                * Don't propagate rate changes up because the only changeable
+                * parents are mpll1 and mpll2 but we need those for audio and
+                * RGMII (Ethernet). We don't want to change the audio or
+                * Ethernet clocks when setting the GPU frequency.
+                */
+               .flags = 0,
+       },
+};
+
+static struct clk_regmap meson8b_mali_0_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .shift = 0,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_0_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "mali_0_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_mali_0 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .bit_idx = 8,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_0",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mali_0_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_mali_1_sel = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .mask = 0x7,
+               .shift = 25,
+               .table = meson8b_mali_0_1_mux_table,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_1_sel",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = meson8b_mali_0_1_parent_names,
+               .num_parents = ARRAY_SIZE(meson8b_mali_0_1_parent_names),
+               /*
+                * Don't propagate rate changes up because the only changeable
+                * parents are mpll1 and mpll2 but we need those for audio and
+                * RGMII (Ethernet). We don't want to change the audio or
+                * Ethernet clocks when setting the GPU frequency.
+                */
+               .flags = 0,
+       },
+};
+
+static struct clk_regmap meson8b_mali_1_div = {
+       .data = &(struct clk_regmap_div_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .shift = 16,
+               .width = 7,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_1_div",
+               .ops = &clk_regmap_divider_ops,
+               .parent_names = (const char *[]){ "mali_1_sel" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_mali_1 = {
+       .data = &(struct clk_regmap_gate_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .bit_idx = 24,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mali_1",
+               .ops = &clk_regmap_gate_ops,
+               .parent_names = (const char *[]){ "mali_1_div" },
+               .num_parents = 1,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
+static struct clk_regmap meson8b_mali = {
+       .data = &(struct clk_regmap_mux_data){
+               .offset = HHI_MALI_CLK_CNTL,
+               .mask = 1,
+               .shift = 31,
+       },
+       .hw.init = &(struct clk_init_data){
+               .name = "mali",
+               .ops = &clk_regmap_mux_ops,
+               .parent_names = (const char *[]){ "mali_0", "mali_1" },
+               .num_parents = 2,
+               .flags = CLK_SET_RATE_PARENT,
+       },
+};
+
 /* Everything Else (EE) domain gates */
 
 static MESON_GATE(meson8b_ddr, HHI_GCLK_MPEG0, 0);
@@ -1659,6 +1789,188 @@ static MESON_GATE(meson8b_ao_ahb_sram, HHI_GCLK_AO, 1);
 static MESON_GATE(meson8b_ao_ahb_bus, HHI_GCLK_AO, 2);
 static MESON_GATE(meson8b_ao_iface, HHI_GCLK_AO, 3);
 
+static struct clk_hw_onecell_data meson8_hw_onecell_data = {
+       .hws = {
+               [CLKID_XTAL] = &meson8b_xtal.hw,
+               [CLKID_PLL_FIXED] = &meson8b_fixed_pll.hw,
+               [CLKID_PLL_VID] = &meson8b_vid_pll.hw,
+               [CLKID_PLL_SYS] = &meson8b_sys_pll.hw,
+               [CLKID_FCLK_DIV2] = &meson8b_fclk_div2.hw,
+               [CLKID_FCLK_DIV3] = &meson8b_fclk_div3.hw,
+               [CLKID_FCLK_DIV4] = &meson8b_fclk_div4.hw,
+               [CLKID_FCLK_DIV5] = &meson8b_fclk_div5.hw,
+               [CLKID_FCLK_DIV7] = &meson8b_fclk_div7.hw,
+               [CLKID_CPUCLK] = &meson8b_cpu_clk.hw,
+               [CLKID_MPEG_SEL] = &meson8b_mpeg_clk_sel.hw,
+               [CLKID_MPEG_DIV] = &meson8b_mpeg_clk_div.hw,
+               [CLKID_CLK81] = &meson8b_clk81.hw,
+               [CLKID_DDR]                 = &meson8b_ddr.hw,
+               [CLKID_DOS]                 = &meson8b_dos.hw,
+               [CLKID_ISA]                 = &meson8b_isa.hw,
+               [CLKID_PL301]               = &meson8b_pl301.hw,
+               [CLKID_PERIPHS]             = &meson8b_periphs.hw,
+               [CLKID_SPICC]               = &meson8b_spicc.hw,
+               [CLKID_I2C]                 = &meson8b_i2c.hw,
+               [CLKID_SAR_ADC]             = &meson8b_sar_adc.hw,
+               [CLKID_SMART_CARD]          = &meson8b_smart_card.hw,
+               [CLKID_RNG0]                = &meson8b_rng0.hw,
+               [CLKID_UART0]               = &meson8b_uart0.hw,
+               [CLKID_SDHC]                = &meson8b_sdhc.hw,
+               [CLKID_STREAM]              = &meson8b_stream.hw,
+               [CLKID_ASYNC_FIFO]          = &meson8b_async_fifo.hw,
+               [CLKID_SDIO]                = &meson8b_sdio.hw,
+               [CLKID_ABUF]                = &meson8b_abuf.hw,
+               [CLKID_HIU_IFACE]           = &meson8b_hiu_iface.hw,
+               [CLKID_ASSIST_MISC]         = &meson8b_assist_misc.hw,
+               [CLKID_SPI]                 = &meson8b_spi.hw,
+               [CLKID_I2S_SPDIF]           = &meson8b_i2s_spdif.hw,
+               [CLKID_ETH]                 = &meson8b_eth.hw,
+               [CLKID_DEMUX]               = &meson8b_demux.hw,
+               [CLKID_AIU_GLUE]            = &meson8b_aiu_glue.hw,
+               [CLKID_IEC958]              = &meson8b_iec958.hw,
+               [CLKID_I2S_OUT]             = &meson8b_i2s_out.hw,
+               [CLKID_AMCLK]               = &meson8b_amclk.hw,
+               [CLKID_AIFIFO2]             = &meson8b_aififo2.hw,
+               [CLKID_MIXER]               = &meson8b_mixer.hw,
+               [CLKID_MIXER_IFACE]         = &meson8b_mixer_iface.hw,
+               [CLKID_ADC]                 = &meson8b_adc.hw,
+               [CLKID_BLKMV]               = &meson8b_blkmv.hw,
+               [CLKID_AIU]                 = &meson8b_aiu.hw,
+               [CLKID_UART1]               = &meson8b_uart1.hw,
+               [CLKID_G2D]                 = &meson8b_g2d.hw,
+               [CLKID_USB0]                = &meson8b_usb0.hw,
+               [CLKID_USB1]                = &meson8b_usb1.hw,
+               [CLKID_RESET]               = &meson8b_reset.hw,
+               [CLKID_NAND]                = &meson8b_nand.hw,
+               [CLKID_DOS_PARSER]          = &meson8b_dos_parser.hw,
+               [CLKID_USB]                 = &meson8b_usb.hw,
+               [CLKID_VDIN1]               = &meson8b_vdin1.hw,
+               [CLKID_AHB_ARB0]            = &meson8b_ahb_arb0.hw,
+               [CLKID_EFUSE]               = &meson8b_efuse.hw,
+               [CLKID_BOOT_ROM]            = &meson8b_boot_rom.hw,
+               [CLKID_AHB_DATA_BUS]        = &meson8b_ahb_data_bus.hw,
+               [CLKID_AHB_CTRL_BUS]        = &meson8b_ahb_ctrl_bus.hw,
+               [CLKID_HDMI_INTR_SYNC]      = &meson8b_hdmi_intr_sync.hw,
+               [CLKID_HDMI_PCLK]           = &meson8b_hdmi_pclk.hw,
+               [CLKID_USB1_DDR_BRIDGE]     = &meson8b_usb1_ddr_bridge.hw,
+               [CLKID_USB0_DDR_BRIDGE]     = &meson8b_usb0_ddr_bridge.hw,
+               [CLKID_MMC_PCLK]            = &meson8b_mmc_pclk.hw,
+               [CLKID_DVIN]                = &meson8b_dvin.hw,
+               [CLKID_UART2]               = &meson8b_uart2.hw,
+               [CLKID_SANA]                = &meson8b_sana.hw,
+               [CLKID_VPU_INTR]            = &meson8b_vpu_intr.hw,
+               [CLKID_SEC_AHB_AHB3_BRIDGE] = &meson8b_sec_ahb_ahb3_bridge.hw,
+               [CLKID_CLK81_A9]            = &meson8b_clk81_a9.hw,
+               [CLKID_VCLK2_VENCI0]        = &meson8b_vclk2_venci0.hw,
+               [CLKID_VCLK2_VENCI1]        = &meson8b_vclk2_venci1.hw,
+               [CLKID_VCLK2_VENCP0]        = &meson8b_vclk2_vencp0.hw,
+               [CLKID_VCLK2_VENCP1]        = &meson8b_vclk2_vencp1.hw,
+               [CLKID_GCLK_VENCI_INT]      = &meson8b_gclk_venci_int.hw,
+               [CLKID_GCLK_VENCP_INT]      = &meson8b_gclk_vencp_int.hw,
+               [CLKID_DAC_CLK]             = &meson8b_dac_clk.hw,
+               [CLKID_AOCLK_GATE]          = &meson8b_aoclk_gate.hw,
+               [CLKID_IEC958_GATE]         = &meson8b_iec958_gate.hw,
+               [CLKID_ENC480P]             = &meson8b_enc480p.hw,
+               [CLKID_RNG1]                = &meson8b_rng1.hw,
+               [CLKID_GCLK_VENCL_INT]      = &meson8b_gclk_vencl_int.hw,
+               [CLKID_VCLK2_VENCLMCC]      = &meson8b_vclk2_venclmcc.hw,
+               [CLKID_VCLK2_VENCL]         = &meson8b_vclk2_vencl.hw,
+               [CLKID_VCLK2_OTHER]         = &meson8b_vclk2_other.hw,
+               [CLKID_EDP]                 = &meson8b_edp.hw,
+               [CLKID_AO_MEDIA_CPU]        = &meson8b_ao_media_cpu.hw,
+               [CLKID_AO_AHB_SRAM]         = &meson8b_ao_ahb_sram.hw,
+               [CLKID_AO_AHB_BUS]          = &meson8b_ao_ahb_bus.hw,
+               [CLKID_AO_IFACE]            = &meson8b_ao_iface.hw,
+               [CLKID_MPLL0]               = &meson8b_mpll0.hw,
+               [CLKID_MPLL1]               = &meson8b_mpll1.hw,
+               [CLKID_MPLL2]               = &meson8b_mpll2.hw,
+               [CLKID_MPLL0_DIV]           = &meson8b_mpll0_div.hw,
+               [CLKID_MPLL1_DIV]           = &meson8b_mpll1_div.hw,
+               [CLKID_MPLL2_DIV]           = &meson8b_mpll2_div.hw,
+               [CLKID_CPU_IN_SEL]          = &meson8b_cpu_in_sel.hw,
+               [CLKID_CPU_IN_DIV2]         = &meson8b_cpu_in_div2.hw,
+               [CLKID_CPU_IN_DIV3]         = &meson8b_cpu_in_div3.hw,
+               [CLKID_CPU_SCALE_DIV]       = &meson8b_cpu_scale_div.hw,
+               [CLKID_CPU_SCALE_OUT_SEL]   = &meson8b_cpu_scale_out_sel.hw,
+               [CLKID_MPLL_PREDIV]         = &meson8b_mpll_prediv.hw,
+               [CLKID_FCLK_DIV2_DIV]       = &meson8b_fclk_div2_div.hw,
+               [CLKID_FCLK_DIV3_DIV]       = &meson8b_fclk_div3_div.hw,
+               [CLKID_FCLK_DIV4_DIV]       = &meson8b_fclk_div4_div.hw,
+               [CLKID_FCLK_DIV5_DIV]       = &meson8b_fclk_div5_div.hw,
+               [CLKID_FCLK_DIV7_DIV]       = &meson8b_fclk_div7_div.hw,
+               [CLKID_NAND_SEL]            = &meson8b_nand_clk_sel.hw,
+               [CLKID_NAND_DIV]            = &meson8b_nand_clk_div.hw,
+               [CLKID_NAND_CLK]            = &meson8b_nand_clk_gate.hw,
+               [CLKID_PLL_FIXED_DCO]       = &meson8b_fixed_pll_dco.hw,
+               [CLKID_HDMI_PLL_DCO]        = &meson8b_hdmi_pll_dco.hw,
+               [CLKID_PLL_SYS_DCO]         = &meson8b_sys_pll_dco.hw,
+               [CLKID_CPU_CLK_DIV2]        = &meson8b_cpu_clk_div2.hw,
+               [CLKID_CPU_CLK_DIV3]        = &meson8b_cpu_clk_div3.hw,
+               [CLKID_CPU_CLK_DIV4]        = &meson8b_cpu_clk_div4.hw,
+               [CLKID_CPU_CLK_DIV5]        = &meson8b_cpu_clk_div5.hw,
+               [CLKID_CPU_CLK_DIV6]        = &meson8b_cpu_clk_div6.hw,
+               [CLKID_CPU_CLK_DIV7]        = &meson8b_cpu_clk_div7.hw,
+               [CLKID_CPU_CLK_DIV8]        = &meson8b_cpu_clk_div8.hw,
+               [CLKID_APB_SEL]             = &meson8b_apb_clk_sel.hw,
+               [CLKID_APB]                 = &meson8b_apb_clk_gate.hw,
+               [CLKID_PERIPH_SEL]          = &meson8b_periph_clk_sel.hw,
+               [CLKID_PERIPH]              = &meson8b_periph_clk_gate.hw,
+               [CLKID_AXI_SEL]             = &meson8b_axi_clk_sel.hw,
+               [CLKID_AXI]                 = &meson8b_axi_clk_gate.hw,
+               [CLKID_L2_DRAM_SEL]         = &meson8b_l2_dram_clk_sel.hw,
+               [CLKID_L2_DRAM]             = &meson8b_l2_dram_clk_gate.hw,
+               [CLKID_HDMI_PLL_LVDS_OUT]   = &meson8b_hdmi_pll_lvds_out.hw,
+               [CLKID_HDMI_PLL_HDMI_OUT]   = &meson8b_hdmi_pll_hdmi_out.hw,
+               [CLKID_VID_PLL_IN_SEL]      = &meson8b_vid_pll_in_sel.hw,
+               [CLKID_VID_PLL_IN_EN]       = &meson8b_vid_pll_in_en.hw,
+               [CLKID_VID_PLL_PRE_DIV]     = &meson8b_vid_pll_pre_div.hw,
+               [CLKID_VID_PLL_POST_DIV]    = &meson8b_vid_pll_post_div.hw,
+               [CLKID_VID_PLL_FINAL_DIV]   = &meson8b_vid_pll_final_div.hw,
+               [CLKID_VCLK_IN_SEL]         = &meson8b_vclk_in_sel.hw,
+               [CLKID_VCLK_IN_EN]          = &meson8b_vclk_in_en.hw,
+               [CLKID_VCLK_DIV1]           = &meson8b_vclk_div1_gate.hw,
+               [CLKID_VCLK_DIV2_DIV]       = &meson8b_vclk_div2_div.hw,
+               [CLKID_VCLK_DIV2]           = &meson8b_vclk_div2_div_gate.hw,
+               [CLKID_VCLK_DIV4_DIV]       = &meson8b_vclk_div4_div.hw,
+               [CLKID_VCLK_DIV4]           = &meson8b_vclk_div4_div_gate.hw,
+               [CLKID_VCLK_DIV6_DIV]       = &meson8b_vclk_div6_div.hw,
+               [CLKID_VCLK_DIV6]           = &meson8b_vclk_div6_div_gate.hw,
+               [CLKID_VCLK_DIV12_DIV]      = &meson8b_vclk_div12_div.hw,
+               [CLKID_VCLK_DIV12]          = &meson8b_vclk_div12_div_gate.hw,
+               [CLKID_VCLK2_IN_SEL]        = &meson8b_vclk2_in_sel.hw,
+               [CLKID_VCLK2_IN_EN]         = &meson8b_vclk2_clk_in_en.hw,
+               [CLKID_VCLK2_DIV1]          = &meson8b_vclk2_div1_gate.hw,
+               [CLKID_VCLK2_DIV2_DIV]      = &meson8b_vclk2_div2_div.hw,
+               [CLKID_VCLK2_DIV2]          = &meson8b_vclk2_div2_div_gate.hw,
+               [CLKID_VCLK2_DIV4_DIV]      = &meson8b_vclk2_div4_div.hw,
+               [CLKID_VCLK2_DIV4]          = &meson8b_vclk2_div4_div_gate.hw,
+               [CLKID_VCLK2_DIV6_DIV]      = &meson8b_vclk2_div6_div.hw,
+               [CLKID_VCLK2_DIV6]          = &meson8b_vclk2_div6_div_gate.hw,
+               [CLKID_VCLK2_DIV12_DIV]     = &meson8b_vclk2_div12_div.hw,
+               [CLKID_VCLK2_DIV12]         = &meson8b_vclk2_div12_div_gate.hw,
+               [CLKID_CTS_ENCT_SEL]        = &meson8b_cts_enct_sel.hw,
+               [CLKID_CTS_ENCT]            = &meson8b_cts_enct.hw,
+               [CLKID_CTS_ENCP_SEL]        = &meson8b_cts_encp_sel.hw,
+               [CLKID_CTS_ENCP]            = &meson8b_cts_encp.hw,
+               [CLKID_CTS_ENCI_SEL]        = &meson8b_cts_enci_sel.hw,
+               [CLKID_CTS_ENCI]            = &meson8b_cts_enci.hw,
+               [CLKID_HDMI_TX_PIXEL_SEL]   = &meson8b_hdmi_tx_pixel_sel.hw,
+               [CLKID_HDMI_TX_PIXEL]       = &meson8b_hdmi_tx_pixel.hw,
+               [CLKID_CTS_ENCL_SEL]        = &meson8b_cts_encl_sel.hw,
+               [CLKID_CTS_ENCL]            = &meson8b_cts_encl.hw,
+               [CLKID_CTS_VDAC0_SEL]       = &meson8b_cts_vdac0_sel.hw,
+               [CLKID_CTS_VDAC0]           = &meson8b_cts_vdac0.hw,
+               [CLKID_HDMI_SYS_SEL]        = &meson8b_hdmi_sys_sel.hw,
+               [CLKID_HDMI_SYS_DIV]        = &meson8b_hdmi_sys_div.hw,
+               [CLKID_HDMI_SYS]            = &meson8b_hdmi_sys.hw,
+               [CLKID_MALI_0_SEL]          = &meson8b_mali_0_sel.hw,
+               [CLKID_MALI_0_DIV]          = &meson8b_mali_0_div.hw,
+               [CLKID_MALI]                = &meson8b_mali_0.hw,
+               [CLK_NR_CLKS]               = NULL,
+       },
+       .num = CLK_NR_CLKS,
+};
+
 static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
        .hws = {
                [CLKID_XTAL] = &meson8b_xtal.hw,
@@ -1781,8 +2093,8 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
                [CLKID_CPU_CLK_DIV6]        = &meson8b_cpu_clk_div6.hw,
                [CLKID_CPU_CLK_DIV7]        = &meson8b_cpu_clk_div7.hw,
                [CLKID_CPU_CLK_DIV8]        = &meson8b_cpu_clk_div8.hw,
-               [CLKID_ABP_SEL]             = &meson8b_abp_clk_sel.hw,
-               [CLKID_ABP]                 = &meson8b_abp_clk_gate.hw,
+               [CLKID_APB_SEL]             = &meson8b_apb_clk_sel.hw,
+               [CLKID_APB]                 = &meson8b_apb_clk_gate.hw,
                [CLKID_PERIPH_SEL]          = &meson8b_periph_clk_sel.hw,
                [CLKID_PERIPH]              = &meson8b_periph_clk_gate.hw,
                [CLKID_AXI_SEL]             = &meson8b_axi_clk_sel.hw,
@@ -1833,6 +2145,13 @@ static struct clk_hw_onecell_data meson8b_hw_onecell_data = {
                [CLKID_HDMI_SYS_SEL]        = &meson8b_hdmi_sys_sel.hw,
                [CLKID_HDMI_SYS_DIV]        = &meson8b_hdmi_sys_div.hw,
                [CLKID_HDMI_SYS]            = &meson8b_hdmi_sys.hw,
+               [CLKID_MALI_0_SEL]          = &meson8b_mali_0_sel.hw,
+               [CLKID_MALI_0_DIV]          = &meson8b_mali_0_div.hw,
+               [CLKID_MALI_0]              = &meson8b_mali_0.hw,
+               [CLKID_MALI_1_SEL]          = &meson8b_mali_1_sel.hw,
+               [CLKID_MALI_1_DIV]          = &meson8b_mali_1_div.hw,
+               [CLKID_MALI_1]              = &meson8b_mali_1.hw,
+               [CLKID_MALI]                = &meson8b_mali.hw,
                [CLK_NR_CLKS]               = NULL,
        },
        .num = CLK_NR_CLKS,
@@ -1943,8 +2262,8 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
        &meson8b_fixed_pll_dco,
        &meson8b_hdmi_pll_dco,
        &meson8b_sys_pll_dco,
-       &meson8b_abp_clk_sel,
-       &meson8b_abp_clk_gate,
+       &meson8b_apb_clk_sel,
+       &meson8b_apb_clk_gate,
        &meson8b_periph_clk_sel,
        &meson8b_periph_clk_gate,
        &meson8b_axi_clk_sel,
@@ -1988,6 +2307,13 @@ static struct clk_regmap *const meson8b_clk_regmaps[] = {
        &meson8b_hdmi_sys_sel,
        &meson8b_hdmi_sys_div,
        &meson8b_hdmi_sys,
+       &meson8b_mali_0_sel,
+       &meson8b_mali_0_div,
+       &meson8b_mali_0,
+       &meson8b_mali_1_sel,
+       &meson8b_mali_1_div,
+       &meson8b_mali_1,
+       &meson8b_mali,
 };
 
 static const struct meson8b_clk_reset_line {
@@ -2132,7 +2458,6 @@ static int meson8b_cpu_clk_notifier_cb(struct notifier_block *nb,
 
 static struct meson8b_nb_data meson8b_cpu_nb_data = {
        .nb.notifier_call = meson8b_cpu_clk_notifier_cb,
-       .onecell_data = &meson8b_hw_onecell_data,
 };
 
 static const struct regmap_config clkc_regmap_config = {
@@ -2141,7 +2466,8 @@ static const struct regmap_config clkc_regmap_config = {
        .reg_stride     = 4,
 };
 
-static void __init meson8b_clkc_init(struct device_node *np)
+static void __init meson8b_clkc_init_common(struct device_node *np,
+                       struct clk_hw_onecell_data *clk_hw_onecell_data)
 {
        struct meson8b_clk_reset *rstc;
        const char *notifier_clk_name;
@@ -2192,14 +2518,16 @@ static void __init meson8b_clkc_init(struct device_node *np)
         */
        for (i = CLKID_XTAL; i < CLK_NR_CLKS; i++) {
                /* array might be sparse */
-               if (!meson8b_hw_onecell_data.hws[i])
+               if (!clk_hw_onecell_data->hws[i])
                        continue;
 
-               ret = clk_hw_register(NULL, meson8b_hw_onecell_data.hws[i]);
+               ret = clk_hw_register(NULL, clk_hw_onecell_data->hws[i]);
                if (ret)
                        return;
        }
 
+       meson8b_cpu_nb_data.onecell_data = clk_hw_onecell_data;
+
        /*
         * FIXME we shouldn't program the muxes in notifier handlers. The
         * tricky programming sequence will be handled by the forthcoming
@@ -2215,13 +2543,23 @@ static void __init meson8b_clkc_init(struct device_node *np)
        }
 
        ret = of_clk_add_hw_provider(np, of_clk_hw_onecell_get,
-                                    &meson8b_hw_onecell_data);
+                                    clk_hw_onecell_data);
        if (ret)
                pr_err("%s: failed to register clock provider\n", __func__);
 }
 
+static void __init meson8_clkc_init(struct device_node *np)
+{
+       return meson8b_clkc_init_common(np, &meson8_hw_onecell_data);
+}
+
+static void __init meson8b_clkc_init(struct device_node *np)
+{
+       return meson8b_clkc_init_common(np, &meson8b_hw_onecell_data);
+}
+
 CLK_OF_DECLARE_DRIVER(meson8_clkc, "amlogic,meson8-clkc",
-                     meson8b_clkc_init);
+                     meson8_clkc_init);
 CLK_OF_DECLARE_DRIVER(meson8b_clkc, "amlogic,meson8b-clkc",
                      meson8b_clkc_init);
 CLK_OF_DECLARE_DRIVER(meson8m2_clkc, "amlogic,meson8m2-clkc",
index 87fba73..b8c58fa 100644 (file)
@@ -33,6 +33,7 @@
 #define HHI_VID_CLK_CNTL2              0x194 /* 0x65 offset in data sheet */
 #define HHI_VID_DIVIDER_CNTL           0x198 /* 0x66 offset in data sheet */
 #define HHI_SYS_CPU_CLK_CNTL0          0x19c /* 0x67 offset in data sheet */
+#define HHI_MALI_CLK_CNTL              0x1b0 /* 0x6c offset in data sheet */
 #define HHI_HDMI_CLK_CNTL              0x1cc /* 0x73 offset in data sheet */
 #define HHI_NAND_CLK_CNTL              0x25c /* 0x97 offset in data sheet */
 #define HHI_MPLL_CNTL                  0x280 /* 0xa0 offset in data sheet */
@@ -91,7 +92,7 @@
 #define CLKID_CPU_CLK_DIV6     120
 #define CLKID_CPU_CLK_DIV7     121
 #define CLKID_CPU_CLK_DIV8     122
-#define CLKID_ABP_SEL          123
+#define CLKID_APB_SEL          123
 #define CLKID_PERIPH_SEL       125
 #define CLKID_AXI_SEL          127
 #define CLKID_L2_DRAM_SEL      129
 #define CLKID_HDMI_SYS_SEL     172
 #define CLKID_HDMI_SYS_DIV     173
 #define CLKID_HDMI_SYS         174
+#define CLKID_MALI_0_SEL       175
+#define CLKID_MALI_0_DIV       176
+#define CLKID_MALI_0           177
+#define CLKID_MALI_1_SEL       178
+#define CLKID_MALI_1_DIV       179
+#define CLKID_MALI_1           180
 
-#define CLK_NR_CLKS            175
+#define CLK_NR_CLKS            181
 
 /*
  * include the CLKID and RESETID that have
diff --git a/drivers/clk/meson/parm.h b/drivers/clk/meson/parm.h
new file mode 100644 (file)
index 0000000..3c9ef1b
--- /dev/null
@@ -0,0 +1,46 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2015 Endless Mobile, Inc.
+ * Author: Carlo Caione <carlo@endlessm.com>
+ */
+
+#ifndef __MESON_PARM_H
+#define __MESON_PARM_H
+
+#include <linux/bits.h>
+#include <linux/regmap.h>
+
+#define PMASK(width)                   GENMASK(width - 1, 0)
+#define SETPMASK(width, shift)         GENMASK(shift + width - 1, shift)
+#define CLRPMASK(width, shift)         (~SETPMASK(width, shift))
+
+#define PARM_GET(width, shift, reg)                                    \
+       (((reg) & SETPMASK(width, shift)) >> (shift))
+#define PARM_SET(width, shift, reg, val)                               \
+       (((reg) & CLRPMASK(width, shift)) | ((val) << (shift)))
+
+#define MESON_PARM_APPLICABLE(p)               (!!((p)->width))
+
+struct parm {
+       u16     reg_off;
+       u8      shift;
+       u8      width;
+};
+
+static inline unsigned int meson_parm_read(struct regmap *map, struct parm *p)
+{
+       unsigned int val;
+
+       regmap_read(map, p->reg_off, &val);
+       return PARM_GET(p->width, p->shift, val);
+}
+
+static inline void meson_parm_write(struct regmap *map, struct parm *p,
+                                   unsigned int val)
+{
+       regmap_update_bits(map, p->reg_off, SETPMASK(p->width, p->shift),
+                          val << p->shift);
+}
+
+#endif /* __MESON_PARM_H */
+
index bc64019..3acf037 100644 (file)
  * duty_cycle = (1 + hi) / (1 + val)
  */
 
-#include "clkc-audio.h"
+#include <linux/clk-provider.h>
+#include <linux/module.h>
+
+#include "clk-regmap.h"
+#include "sclk-div.h"
 
 static inline struct meson_sclk_div_data *
 meson_sclk_div_data(struct clk_regmap *clk)
@@ -241,3 +245,7 @@ const struct clk_ops meson_sclk_div_ops = {
        .init           = sclk_div_init,
 };
 EXPORT_SYMBOL_GPL(meson_sclk_div_ops);
+
+MODULE_DESCRIPTION("Amlogic Sample divider driver");
+MODULE_AUTHOR("Jerome Brunet <jbrunet@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/sclk-div.h b/drivers/clk/meson/sclk-div.h
new file mode 100644 (file)
index 0000000..b64b2a3
--- /dev/null
@@ -0,0 +1,22 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2018 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+#ifndef __MESON_SCLK_DIV_H
+#define __MESON_SCLK_DIV_H
+
+#include <linux/clk-provider.h>
+#include "parm.h"
+
+struct meson_sclk_div_data {
+       struct parm div;
+       struct parm hi;
+       unsigned int cached_div;
+       struct clk_duty cached_duty;
+};
+
+extern const struct clk_ops meson_sclk_div_ops;
+
+#endif /* __MESON_SCLK_DIV_H */
index 88af0e2..08bcc01 100644 (file)
@@ -5,7 +5,10 @@
  */
 
 #include <linux/clk-provider.h>
-#include "clkc.h"
+#include <linux/module.h>
+
+#include "clk-regmap.h"
+#include "vid-pll-div.h"
 
 static inline struct meson_vid_pll_div_data *
 meson_vid_pll_div_data(struct clk_regmap *clk)
@@ -89,3 +92,8 @@ static unsigned long meson_vid_pll_div_recalc_rate(struct clk_hw *hw,
 const struct clk_ops meson_vid_pll_div_ro_ops = {
        .recalc_rate    = meson_vid_pll_div_recalc_rate,
 };
+EXPORT_SYMBOL_GPL(meson_vid_pll_div_ro_ops);
+
+MODULE_DESCRIPTION("Amlogic video pll divider driver");
+MODULE_AUTHOR("Neil Armstrong <narmstrong@baylibre.com>");
+MODULE_LICENSE("GPL v2");
diff --git a/drivers/clk/meson/vid-pll-div.h b/drivers/clk/meson/vid-pll-div.h
new file mode 100644 (file)
index 0000000..c0128e3
--- /dev/null
@@ -0,0 +1,20 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright (c) 2019 BayLibre, SAS.
+ * Author: Jerome Brunet <jbrunet@baylibre.com>
+ */
+
+#ifndef __MESON_VID_PLL_DIV_H
+#define __MESON_VID_PLL_DIV_H
+
+#include <linux/clk-provider.h>
+#include "parm.h"
+
+struct meson_vid_pll_div_data {
+       struct parm val;
+       struct parm sel;
+};
+
+extern const struct clk_ops meson_vid_pll_div_ro_ops;
+
+#endif /* __MESON_VID_PLL_DIV_H */
index 61fefc0..a60a1be 100644 (file)
@@ -53,7 +53,6 @@
 #define APMU_DISP1     0x110
 #define APMU_CCIC0     0x50
 #define APMU_CCIC1     0xf4
-#define APMU_SP                0x68
 #define MPMU_UART_PLL  0x14
 
 struct mmp2_clk_unit {
@@ -210,8 +209,6 @@ static struct mmp_clk_mix_config ccic1_mix_config = {
        .reg_info = DEFINE_MIX_REG_INFO(4, 16, 2, 6, 32),
 };
 
-static DEFINE_SPINLOCK(sp_lock);
-
 static struct mmp_param_mux_clk apmu_mux_clks[] = {
        {MMP2_CLK_DISP0_MUX, "disp0_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP0, 6, 2, 0, &disp0_lock},
        {MMP2_CLK_DISP1_MUX, "disp1_mux", disp_parent_names, ARRAY_SIZE(disp_parent_names), CLK_SET_RATE_PARENT, APMU_DISP1, 6, 2, 0, &disp1_lock},
@@ -232,9 +229,10 @@ static struct mmp_param_gate_clk apmu_gate_clks[] = {
        {MMP2_CLK_SDH1, "sdh1_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH1, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
        {MMP2_CLK_SDH2, "sdh2_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH2, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
        {MMP2_CLK_SDH3, "sdh3_clk", "sdh_mix_clk", CLK_SET_RATE_PARENT, APMU_SDH3, 0x1b, 0x1b, 0x0, 0, &sdh_lock},
-       {MMP2_CLK_DISP0, "disp0_clk", "disp0_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1b, 0x1b, 0x0, 0, &disp0_lock},
+       {MMP2_CLK_DISP0, "disp0_clk", "disp0_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x09, 0x09, 0x0, 0, &disp0_lock},
+       {MMP2_CLK_DISP0_LCDC, "disp0_lcdc_clk", "disp0_mux", CLK_SET_RATE_PARENT, APMU_DISP0, 0x12, 0x12, 0x0, 0, &disp0_lock},
        {MMP2_CLK_DISP0_SPHY, "disp0_sphy_clk", "disp0_sphy_div", CLK_SET_RATE_PARENT, APMU_DISP0, 0x1024, 0x1024, 0x0, 0, &disp0_lock},
-       {MMP2_CLK_DISP1, "disp1_clk", "disp1_div", CLK_SET_RATE_PARENT, APMU_DISP1, 0x1b, 0x1b, 0x0, 0, &disp1_lock},
+       {MMP2_CLK_DISP1, "disp1_clk", "disp1_div", CLK_SET_RATE_PARENT, APMU_DISP1, 0x09, 0x09, 0x0, 0, &disp1_lock},
        {MMP2_CLK_CCIC_ARBITER, "ccic_arbiter", "vctcxo", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x1800, 0x1800, 0x0, 0, &ccic0_lock},
        {MMP2_CLK_CCIC0, "ccic0_clk", "ccic0_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x1b, 0x1b, 0x0, 0, &ccic0_lock},
        {MMP2_CLK_CCIC0_PHY, "ccic0_phy_clk", "ccic0_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC0, 0x24, 0x24, 0x0, 0, &ccic0_lock},
@@ -242,7 +240,6 @@ static struct mmp_param_gate_clk apmu_gate_clks[] = {
        {MMP2_CLK_CCIC1, "ccic1_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x1b, 0x1b, 0x0, 0, &ccic1_lock},
        {MMP2_CLK_CCIC1_PHY, "ccic1_phy_clk", "ccic1_mix_clk", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x24, 0x24, 0x0, 0, &ccic1_lock},
        {MMP2_CLK_CCIC1_SPHY, "ccic1_sphy_clk", "ccic1_sphy_div", CLK_SET_RATE_PARENT, APMU_CCIC1, 0x300, 0x300, 0x0, 0, &ccic1_lock},
-       {MMP2_CLK_SP, "sp_clk", NULL, CLK_SET_RATE_PARENT, APMU_SP, 0x1b, 0x1b, 0x0, 0, &sp_lock},
 };
 
 static void mmp2_axi_periph_clk_init(struct mmp2_clk_unit *pxa_unit)
index 7dedfaa..5c6bbee 100644 (file)
@@ -175,8 +175,10 @@ static void __init a370_clk_init(struct device_node *np)
 
        mvebu_coreclk_setup(np, &a370_coreclks);
 
-       if (cgnp)
+       if (cgnp) {
                mvebu_clk_gating_setup(cgnp, a370_gating_desc);
+               of_node_put(cgnp);
+       }
 }
 CLK_OF_DECLARE(a370_clk, "marvell,armada-370-core-clock", a370_clk_init);
 
index e8f0329..fa15682 100644 (file)
@@ -226,7 +226,9 @@ static void __init axp_clk_init(struct device_node *np)
 
        mvebu_coreclk_setup(np, &axp_coreclks);
 
-       if (cgnp)
+       if (cgnp) {
                mvebu_clk_gating_setup(cgnp, axp_gating_desc);
+               of_node_put(cgnp);
+       }
 }
 CLK_OF_DECLARE(axp_clk, "marvell,armada-xp-core-clock", axp_clk_init);
index e0dd99f..0bd09d3 100644 (file)
@@ -188,10 +188,14 @@ static void __init dove_clk_init(struct device_node *np)
 
        mvebu_coreclk_setup(np, &dove_coreclks);
 
-       if (ddnp)
+       if (ddnp) {
                dove_divider_clk_init(ddnp);
+               of_node_put(ddnp);
+       }
 
-       if (cgnp)
+       if (cgnp) {
                mvebu_clk_gating_setup(cgnp, dove_gating_desc);
+               of_node_put(cgnp);
+       }
 }
 CLK_OF_DECLARE(dove_clk, "marvell,dove-core-clock", dove_clk_init);
index 6f78416..35af3aa 100644 (file)
@@ -331,6 +331,8 @@ static void __init kirkwood_clk_init(struct device_node *np)
        if (cgnp) {
                mvebu_clk_gating_setup(cgnp, kirkwood_gating_desc);
                kirkwood_clk_muxing_setup(cgnp, kirkwood_mux_desc);
+
+               of_node_put(cgnp);
        }
 }
 CLK_OF_DECLARE(kirkwood_clk, "marvell,kirkwood-core-clock",
index 0a74cf7..1c8ab4f 100644 (file)
@@ -172,7 +172,9 @@ static void __init mv98dx3236_clk_init(struct device_node *np)
 
        mvebu_coreclk_setup(np, &mv98dx3236_core_clocks);
 
-       if (cgnp)
+       if (cgnp) {
                mvebu_clk_gating_setup(cgnp, mv98dx3236_gating_desc);
+               of_node_put(cgnp);
+       }
 }
 CLK_OF_DECLARE(mv98dx3236_clk, "marvell,mv98dx3236-core-clock", mv98dx3236_clk_init);
index 1b1ba54..1c04575 100644 (file)
@@ -215,6 +215,7 @@ config MSM_MMCC_8996
 
 config MSM_GCC_8998
        tristate "MSM8998 Global Clock Controller"
+       select QCOM_GDSC
        help
          Support for the global clock controller on msm8998 devices.
          Say Y if you want to use peripheral devices such as UART, SPI,
index e5eca8a..c25b57c 100644 (file)
@@ -71,7 +71,6 @@ struct src_sel {
  * @freq_tbl: frequency table
  * @clkr: regmap clock handle
  * @lock: register lock
- *
  */
 struct clk_rcg {
        u32             ns_reg;
@@ -107,7 +106,6 @@ extern const struct clk_ops clk_rcg_lcc_ops;
  * @freq_tbl: frequency table
  * @clkr: regmap clock handle
  * @lock: register lock
- *
  */
 struct clk_dyn_rcg {
        u32     ns_reg[2];
@@ -140,7 +138,7 @@ extern const struct clk_ops clk_dyn_rcg_ops;
  * @parent_map: map from software's parent index to hardware's src_sel field
  * @freq_tbl: frequency table
  * @clkr: regmap clock handle
- *
+ * @cfg_off: defines the cfg register offset from the CMD_RCGR + CFG_REG
  */
 struct clk_rcg2 {
        u32                     cmd_rcgr;
@@ -150,6 +148,7 @@ struct clk_rcg2 {
        const struct parent_map *parent_map;
        const struct freq_tbl   *freq_tbl;
        struct clk_regmap       clkr;
+       u8                      cfg_off;
 };
 
 #define to_clk_rcg2(_hw) container_of(to_clk_regmap(_hw), struct clk_rcg2, clkr)
index 6e3bd19..8c02bff 100644 (file)
 #define N_REG                  0xc
 #define D_REG                  0x10
 
+#define RCG_CFG_OFFSET(rcg)    ((rcg)->cmd_rcgr + (rcg)->cfg_off + CFG_REG)
+#define RCG_M_OFFSET(rcg)      ((rcg)->cmd_rcgr + (rcg)->cfg_off + M_REG)
+#define RCG_N_OFFSET(rcg)      ((rcg)->cmd_rcgr + (rcg)->cfg_off + N_REG)
+#define RCG_D_OFFSET(rcg)      ((rcg)->cmd_rcgr + (rcg)->cfg_off + D_REG)
+
 /* Dynamic Frequency Scaling */
 #define MAX_PERF_LEVEL         8
 #define SE_CMD_DFSR_OFFSET     0x14
@@ -74,7 +79,7 @@ static u8 clk_rcg2_get_parent(struct clk_hw *hw)
        u32 cfg;
        int i, ret;
 
-       ret = regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
+       ret = regmap_read(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), &cfg);
        if (ret)
                goto err;
 
@@ -123,7 +128,7 @@ static int clk_rcg2_set_parent(struct clk_hw *hw, u8 index)
        int ret;
        u32 cfg = rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
 
-       ret = regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
+       ret = regmap_update_bits(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg),
                                 CFG_SRC_SEL_MASK, cfg);
        if (ret)
                return ret;
@@ -162,13 +167,13 @@ clk_rcg2_recalc_rate(struct clk_hw *hw, unsigned long parent_rate)
        struct clk_rcg2 *rcg = to_clk_rcg2(hw);
        u32 cfg, hid_div, m = 0, n = 0, mode = 0, mask;
 
-       regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG, &cfg);
+       regmap_read(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg), &cfg);
 
        if (rcg->mnd_width) {
                mask = BIT(rcg->mnd_width) - 1;
-               regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + M_REG, &m);
+               regmap_read(rcg->clkr.regmap, RCG_M_OFFSET(rcg), &m);
                m &= mask;
-               regmap_read(rcg->clkr.regmap, rcg->cmd_rcgr + N_REG, &n);
+               regmap_read(rcg->clkr.regmap, RCG_N_OFFSET(rcg), &n);
                n =  ~n;
                n &= mask;
                n += m;
@@ -263,17 +268,17 @@ static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
        if (rcg->mnd_width && f->n) {
                mask = BIT(rcg->mnd_width) - 1;
                ret = regmap_update_bits(rcg->clkr.regmap,
-                               rcg->cmd_rcgr + M_REG, mask, f->m);
+                               RCG_M_OFFSET(rcg), mask, f->m);
                if (ret)
                        return ret;
 
                ret = regmap_update_bits(rcg->clkr.regmap,
-                               rcg->cmd_rcgr + N_REG, mask, ~(f->n - f->m));
+                               RCG_N_OFFSET(rcg), mask, ~(f->n - f->m));
                if (ret)
                        return ret;
 
                ret = regmap_update_bits(rcg->clkr.regmap,
-                               rcg->cmd_rcgr + D_REG, mask, ~f->n);
+                               RCG_D_OFFSET(rcg), mask, ~f->n);
                if (ret)
                        return ret;
        }
@@ -284,8 +289,7 @@ static int __clk_rcg2_configure(struct clk_rcg2 *rcg, const struct freq_tbl *f)
        cfg |= rcg->parent_map[index].cfg << CFG_SRC_SEL_SHIFT;
        if (rcg->mnd_width && f->n && (f->m != f->n))
                cfg |= CFG_MODE_DUAL_EDGE;
-
-       return regmap_update_bits(rcg->clkr.regmap, rcg->cmd_rcgr + CFG_REG,
+       return regmap_update_bits(rcg->clkr.regmap, RCG_CFG_OFFSET(rcg),
                                        mask, cfg);
 }
 
index 9f4fc77..c3fd632 100644 (file)
 #define CLK_RPMH_ARC_EN_OFFSET         0
 #define CLK_RPMH_VRM_EN_OFFSET         4
 
+#define BCM_TCS_CMD_COMMIT_MASK                0x40000000
+#define BCM_TCS_CMD_VALID_SHIFT                29
+#define BCM_TCS_CMD_VOTE_MASK          0x3fff
+#define BCM_TCS_CMD_VOTE_SHIFT         0
+
+#define BCM_TCS_CMD(valid, vote)                               \
+       (BCM_TCS_CMD_COMMIT_MASK |                              \
+       ((valid) << BCM_TCS_CMD_VALID_SHIFT) |                  \
+       ((vote & BCM_TCS_CMD_VOTE_MASK)                         \
+       << BCM_TCS_CMD_VOTE_SHIFT))
+
+/**
+ * struct bcm_db - Auxiliary data pertaining to each Bus Clock Manager(BCM)
+ * @unit: divisor used to convert Hz value to an RPMh msg
+ * @width: multiplier used to convert Hz value to an RPMh msg
+ * @vcd: virtual clock domain that this bcm belongs to
+ * @reserved: reserved to pad the struct
+ */
+struct bcm_db {
+       __le32 unit;
+       __le16 width;
+       u8 vcd;
+       u8 reserved;
+};
+
 /**
  * struct clk_rpmh - individual rpmh clock data structure
  * @hw:                        handle between common and hardware-specific interfaces
@@ -29,6 +54,7 @@
  * @aggr_state:                rpmh clock aggregated state
  * @last_sent_aggr_state: rpmh clock last aggr state sent to RPMh
  * @valid_state_mask:  mask to determine the state of the rpmh clock
+ * @unit:              divisor to convert rate to rpmh msg in magnitudes of Khz
  * @dev:               device to which it is attached
  * @peer:              pointer to the clock rpmh sibling
  */
@@ -42,6 +68,7 @@ struct clk_rpmh {
        u32 aggr_state;
        u32 last_sent_aggr_state;
        u32 valid_state_mask;
+       u32 unit;
        struct device *dev;
        struct clk_rpmh *peer;
 };
@@ -98,6 +125,17 @@ static DEFINE_MUTEX(rpmh_clk_lock);
        __DEFINE_CLK_RPMH(_platform, _name, _name_active, _res_name,    \
                          CLK_RPMH_VRM_EN_OFFSET, 1, _div)
 
+#define DEFINE_CLK_RPMH_BCM(_platform, _name, _res_name)               \
+       static struct clk_rpmh _platform##_##_name = {                  \
+               .res_name = _res_name,                                  \
+               .valid_state_mask = BIT(RPMH_ACTIVE_ONLY_STATE),        \
+               .div = 1,                                               \
+               .hw.init = &(struct clk_init_data){                     \
+                       .ops = &clk_rpmh_bcm_ops,                       \
+                       .name = #_name,                                 \
+               },                                                      \
+       }
+
 static inline struct clk_rpmh *to_clk_rpmh(struct clk_hw *_hw)
 {
        return container_of(_hw, struct clk_rpmh, hw);
@@ -210,6 +248,96 @@ static const struct clk_ops clk_rpmh_ops = {
        .recalc_rate    = clk_rpmh_recalc_rate,
 };
 
+static int clk_rpmh_bcm_send_cmd(struct clk_rpmh *c, bool enable)
+{
+       struct tcs_cmd cmd = { 0 };
+       u32 cmd_state;
+       int ret;
+
+       mutex_lock(&rpmh_clk_lock);
+
+       cmd_state = 0;
+       if (enable) {
+               cmd_state = 1;
+               if (c->aggr_state)
+                       cmd_state = c->aggr_state;
+       }
+
+       if (c->last_sent_aggr_state == cmd_state) {
+               mutex_unlock(&rpmh_clk_lock);
+               return 0;
+       }
+
+       cmd.addr = c->res_addr;
+       cmd.data = BCM_TCS_CMD(enable, cmd_state);
+
+       ret = rpmh_write_async(c->dev, RPMH_ACTIVE_ONLY_STATE, &cmd, 1);
+       if (ret) {
+               dev_err(c->dev, "set active state of %s failed: (%d)\n",
+                       c->res_name, ret);
+               mutex_unlock(&rpmh_clk_lock);
+               return ret;
+       }
+
+       c->last_sent_aggr_state = cmd_state;
+
+       mutex_unlock(&rpmh_clk_lock);
+
+       return 0;
+}
+
+static int clk_rpmh_bcm_prepare(struct clk_hw *hw)
+{
+       struct clk_rpmh *c = to_clk_rpmh(hw);
+
+       return clk_rpmh_bcm_send_cmd(c, true);
+};
+
+static void clk_rpmh_bcm_unprepare(struct clk_hw *hw)
+{
+       struct clk_rpmh *c = to_clk_rpmh(hw);
+
+       clk_rpmh_bcm_send_cmd(c, false);
+};
+
+static int clk_rpmh_bcm_set_rate(struct clk_hw *hw, unsigned long rate,
+                                unsigned long parent_rate)
+{
+       struct clk_rpmh *c = to_clk_rpmh(hw);
+
+       c->aggr_state = rate / c->unit;
+       /*
+        * Since any non-zero value sent to hw would result in enabling the
+        * clock, only send the value if the clock has already been prepared.
+        */
+       if (clk_hw_is_prepared(hw))
+               clk_rpmh_bcm_send_cmd(c, true);
+
+       return 0;
+};
+
+static long clk_rpmh_round_rate(struct clk_hw *hw, unsigned long rate,
+                               unsigned long *parent_rate)
+{
+       return rate;
+}
+
+static unsigned long clk_rpmh_bcm_recalc_rate(struct clk_hw *hw,
+                                       unsigned long prate)
+{
+       struct clk_rpmh *c = to_clk_rpmh(hw);
+
+       return c->aggr_state * c->unit;
+}
+
+static const struct clk_ops clk_rpmh_bcm_ops = {
+       .prepare        = clk_rpmh_bcm_prepare,
+       .unprepare      = clk_rpmh_bcm_unprepare,
+       .set_rate       = clk_rpmh_bcm_set_rate,
+       .round_rate     = clk_rpmh_round_rate,
+       .recalc_rate    = clk_rpmh_bcm_recalc_rate,
+};
+
 /* Resource name must match resource id present in cmd-db. */
 DEFINE_CLK_RPMH_ARC(sdm845, bi_tcxo, bi_tcxo_ao, "xo.lvl", 0x3, 2);
 DEFINE_CLK_RPMH_VRM(sdm845, ln_bb_clk2, ln_bb_clk2_ao, "lnbclka2", 2);
@@ -217,6 +345,7 @@ DEFINE_CLK_RPMH_VRM(sdm845, ln_bb_clk3, ln_bb_clk3_ao, "lnbclka3", 2);
 DEFINE_CLK_RPMH_VRM(sdm845, rf_clk1, rf_clk1_ao, "rfclka1", 1);
 DEFINE_CLK_RPMH_VRM(sdm845, rf_clk2, rf_clk2_ao, "rfclka2", 1);
 DEFINE_CLK_RPMH_VRM(sdm845, rf_clk3, rf_clk3_ao, "rfclka3", 1);
+DEFINE_CLK_RPMH_BCM(sdm845, ipa, "IP0");
 
 static struct clk_hw *sdm845_rpmh_clocks[] = {
        [RPMH_CXO_CLK]          = &sdm845_bi_tcxo.hw,
@@ -231,6 +360,7 @@ static struct clk_hw *sdm845_rpmh_clocks[] = {
        [RPMH_RF_CLK2_A]        = &sdm845_rf_clk2_ao.hw,
        [RPMH_RF_CLK3]          = &sdm845_rf_clk3.hw,
        [RPMH_RF_CLK3_A]        = &sdm845_rf_clk3_ao.hw,
+       [RPMH_IPA_CLK]          = &sdm845_ipa.hw,
 };
 
 static const struct clk_rpmh_desc clk_rpmh_sdm845 = {
@@ -267,6 +397,8 @@ static int clk_rpmh_probe(struct platform_device *pdev)
 
        for (i = 0; i < desc->num_clks; i++) {
                u32 res_addr;
+               size_t aux_data_len;
+               const struct bcm_db *data;
 
                rpmh_clk = to_clk_rpmh(hw_clks[i]);
                res_addr = cmd_db_read_addr(rpmh_clk->res_name);
@@ -275,6 +407,20 @@ static int clk_rpmh_probe(struct platform_device *pdev)
                                rpmh_clk->res_name);
                        return -ENODEV;
                }
+
+               data = cmd_db_read_aux_data(rpmh_clk->res_name, &aux_data_len);
+               if (IS_ERR(data)) {
+                       ret = PTR_ERR(data);
+                       dev_err(&pdev->dev,
+                               "error reading RPMh aux data for %s (%d)\n",
+                               rpmh_clk->res_name, ret);
+                       return ret;
+               }
+
+               /* Convert unit from Khz to Hz */
+               if (aux_data_len == sizeof(*data))
+                       rpmh_clk->unit = le32_to_cpu(data->unit) * 1000ULL;
+
                rpmh_clk->res_addr += res_addr;
                rpmh_clk->dev = &pdev->dev;
 
index d3aadae..22dd42a 100644 (file)
@@ -655,10 +655,73 @@ static const struct rpm_smd_clk_desc rpm_clk_qcs404 = {
        .num_clks = ARRAY_SIZE(qcs404_clks),
 };
 
+/* msm8998 */
+DEFINE_CLK_SMD_RPM(msm8998, snoc_clk, snoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 1);
+DEFINE_CLK_SMD_RPM(msm8998, cnoc_clk, cnoc_a_clk, QCOM_SMD_RPM_BUS_CLK, 2);
+DEFINE_CLK_SMD_RPM(msm8998, ce1_clk, ce1_a_clk, QCOM_SMD_RPM_CE_CLK, 0);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, div_clk1, div_clk1_a, 0xb);
+DEFINE_CLK_SMD_RPM(msm8998, ipa_clk, ipa_a_clk, QCOM_SMD_RPM_IPA_CLK, 0);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, ln_bb_clk1, ln_bb_clk1_a, 1);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, ln_bb_clk2, ln_bb_clk2_a, 2);
+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, ln_bb_clk3_pin, ln_bb_clk3_a_pin,
+                                    3);
+DEFINE_CLK_SMD_RPM(msm8998, mmssnoc_axi_rpm_clk, mmssnoc_axi_rpm_a_clk,
+                  QCOM_SMD_RPM_MMAXI_CLK, 0);
+DEFINE_CLK_SMD_RPM(msm8998, aggre1_noc_clk, aggre1_noc_a_clk,
+                  QCOM_SMD_RPM_AGGR_CLK, 1);
+DEFINE_CLK_SMD_RPM(msm8998, aggre2_noc_clk, aggre2_noc_a_clk,
+                  QCOM_SMD_RPM_AGGR_CLK, 2);
+DEFINE_CLK_SMD_RPM_QDSS(msm8998, qdss_clk, qdss_a_clk,
+                       QCOM_SMD_RPM_MISC_CLK, 1);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, rf_clk1, rf_clk1_a, 4);
+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk2_pin, rf_clk2_a_pin, 5);
+DEFINE_CLK_SMD_RPM_XO_BUFFER(msm8998, rf_clk3, rf_clk3_a, 6);
+DEFINE_CLK_SMD_RPM_XO_BUFFER_PINCTRL(msm8998, rf_clk3_pin, rf_clk3_a_pin, 6);
+static struct clk_smd_rpm *msm8998_clks[] = {
+       [RPM_SMD_SNOC_CLK] = &msm8998_snoc_clk,
+       [RPM_SMD_SNOC_A_CLK] = &msm8998_snoc_a_clk,
+       [RPM_SMD_CNOC_CLK] = &msm8998_cnoc_clk,
+       [RPM_SMD_CNOC_A_CLK] = &msm8998_cnoc_a_clk,
+       [RPM_SMD_CE1_CLK] = &msm8998_ce1_clk,
+       [RPM_SMD_CE1_A_CLK] = &msm8998_ce1_a_clk,
+       [RPM_SMD_DIV_CLK1] = &msm8998_div_clk1,
+       [RPM_SMD_DIV_A_CLK1] = &msm8998_div_clk1_a,
+       [RPM_SMD_IPA_CLK] = &msm8998_ipa_clk,
+       [RPM_SMD_IPA_A_CLK] = &msm8998_ipa_a_clk,
+       [RPM_SMD_LN_BB_CLK1] = &msm8998_ln_bb_clk1,
+       [RPM_SMD_LN_BB_CLK1_A] = &msm8998_ln_bb_clk1_a,
+       [RPM_SMD_LN_BB_CLK2] = &msm8998_ln_bb_clk2,
+       [RPM_SMD_LN_BB_CLK2_A] = &msm8998_ln_bb_clk2_a,
+       [RPM_SMD_LN_BB_CLK3_PIN] = &msm8998_ln_bb_clk3_pin,
+       [RPM_SMD_LN_BB_CLK3_A_PIN] = &msm8998_ln_bb_clk3_a_pin,
+       [RPM_SMD_MMAXI_CLK] = &msm8998_mmssnoc_axi_rpm_clk,
+       [RPM_SMD_MMAXI_A_CLK] = &msm8998_mmssnoc_axi_rpm_a_clk,
+       [RPM_SMD_AGGR1_NOC_CLK] = &msm8998_aggre1_noc_clk,
+       [RPM_SMD_AGGR1_NOC_A_CLK] = &msm8998_aggre1_noc_a_clk,
+       [RPM_SMD_AGGR2_NOC_CLK] = &msm8998_aggre2_noc_clk,
+       [RPM_SMD_AGGR2_NOC_A_CLK] = &msm8998_aggre2_noc_a_clk,
+       [RPM_SMD_QDSS_CLK] = &msm8998_qdss_clk,
+       [RPM_SMD_QDSS_A_CLK] = &msm8998_qdss_a_clk,
+       [RPM_SMD_RF_CLK1] = &msm8998_rf_clk1,
+       [RPM_SMD_RF_CLK1_A] = &msm8998_rf_clk1_a,
+       [RPM_SMD_RF_CLK2_PIN] = &msm8998_rf_clk2_pin,
+       [RPM_SMD_RF_CLK2_A_PIN] = &msm8998_rf_clk2_a_pin,
+       [RPM_SMD_RF_CLK3] = &msm8998_rf_clk3,
+       [RPM_SMD_RF_CLK3_A] = &msm8998_rf_clk3_a,
+       [RPM_SMD_RF_CLK3_PIN] = &msm8998_rf_clk3_pin,
+       [RPM_SMD_RF_CLK3_A_PIN] = &msm8998_rf_clk3_a_pin,
+};
+
+static const struct rpm_smd_clk_desc rpm_clk_msm8998 = {
+       .clks = msm8998_clks,
+       .num_clks = ARRAY_SIZE(msm8998_clks),
+};
+
 static const struct of_device_id rpm_smd_clk_match_table[] = {
        { .compatible = "qcom,rpmcc-msm8916", .data = &rpm_clk_msm8916 },
        { .compatible = "qcom,rpmcc-msm8974", .data = &rpm_clk_msm8974 },
        { .compatible = "qcom,rpmcc-msm8996", .data = &rpm_clk_msm8996 },
+       { .compatible = "qcom,rpmcc-msm8998", .data = &rpm_clk_msm8998 },
        { .compatible = "qcom,rpmcc-qcs404",  .data = &rpm_clk_qcs404  },
        { }
 };
index 0a48ed5..a6b2f86 100644 (file)
@@ -231,6 +231,8 @@ int qcom_cc_really_probe(struct platform_device *pdev,
        struct gdsc_desc *scd;
        size_t num_clks = desc->num_clks;
        struct clk_regmap **rclks = desc->clks;
+       size_t num_clk_hws = desc->num_clk_hws;
+       struct clk_hw **clk_hws = desc->clk_hws;
 
        cc = devm_kzalloc(dev, sizeof(*cc), GFP_KERNEL);
        if (!cc)
@@ -269,6 +271,12 @@ int qcom_cc_really_probe(struct platform_device *pdev,
 
        qcom_cc_drop_protected(dev, cc);
 
+       for (i = 0; i < num_clk_hws; i++) {
+               ret = devm_clk_hw_register(dev, clk_hws[i]);
+               if (ret)
+                       return ret;
+       }
+
        for (i = 0; i < num_clks; i++) {
                if (!rclks[i])
                        continue;
index 4aa33ee..1e2a8bd 100644 (file)
@@ -27,6 +27,8 @@ struct qcom_cc_desc {
        size_t num_resets;
        struct gdsc **gdscs;
        size_t num_gdscs;
+       struct clk_hw **clk_hws;
+       size_t num_clk_hws;
 };
 
 /**
index 505c626..0e32892 100644 (file)
@@ -4715,18 +4715,12 @@ static const struct qcom_cc_desc gcc_ipq8074_desc = {
        .num_clks = ARRAY_SIZE(gcc_ipq8074_clks),
        .resets = gcc_ipq8074_resets,
        .num_resets = ARRAY_SIZE(gcc_ipq8074_resets),
+       .clk_hws = gcc_ipq8074_hws,
+       .num_clk_hws = ARRAY_SIZE(gcc_ipq8074_hws),
 };
 
 static int gcc_ipq8074_probe(struct platform_device *pdev)
 {
-       int ret, i;
-
-       for (i = 0; i < ARRAY_SIZE(gcc_ipq8074_hws); i++) {
-               ret = devm_clk_hw_register(&pdev->dev, gcc_ipq8074_hws[i]);
-               if (ret)
-                       return ret;
-       }
-
        return qcom_cc_probe(pdev, &gcc_ipq8074_desc);
 }
 
index 849046f..8c6d931 100644 (file)
@@ -1702,6 +1702,8 @@ static const struct qcom_cc_desc gcc_mdm9615_desc = {
        .num_clks = ARRAY_SIZE(gcc_mdm9615_clks),
        .resets = gcc_mdm9615_resets,
        .num_resets = ARRAY_SIZE(gcc_mdm9615_resets),
+       .clk_hws = gcc_mdm9615_hws,
+       .num_clk_hws = ARRAY_SIZE(gcc_mdm9615_hws),
 };
 
 static const struct of_device_id gcc_mdm9615_match_table[] = {
@@ -1712,21 +1714,12 @@ MODULE_DEVICE_TABLE(of, gcc_mdm9615_match_table);
 
 static int gcc_mdm9615_probe(struct platform_device *pdev)
 {
-       struct device *dev = &pdev->dev;
        struct regmap *regmap;
-       int ret;
-       int i;
 
        regmap = qcom_cc_map(pdev, &gcc_mdm9615_desc);
        if (IS_ERR(regmap))
                return PTR_ERR(regmap);
 
-       for (i = 0; i < ARRAY_SIZE(gcc_mdm9615_hws); i++) {
-               ret = devm_clk_hw_register(dev, gcc_mdm9615_hws[i]);
-               if (ret)
-                       return ret;
-       }
-
        return qcom_cc_really_probe(pdev, &gcc_mdm9615_desc, regmap);
 }
 
index 9d13617..4632b92 100644 (file)
@@ -3656,6 +3656,8 @@ static const struct qcom_cc_desc gcc_msm8996_desc = {
        .num_resets = ARRAY_SIZE(gcc_msm8996_resets),
        .gdscs = gcc_msm8996_gdscs,
        .num_gdscs = ARRAY_SIZE(gcc_msm8996_gdscs),
+       .clk_hws = gcc_msm8996_hws,
+       .num_clk_hws = ARRAY_SIZE(gcc_msm8996_hws),
 };
 
 static const struct of_device_id gcc_msm8996_match_table[] = {
@@ -3666,8 +3668,6 @@ MODULE_DEVICE_TABLE(of, gcc_msm8996_match_table);
 
 static int gcc_msm8996_probe(struct platform_device *pdev)
 {
-       struct device *dev = &pdev->dev;
-       int i, ret;
        struct regmap *regmap;
 
        regmap = qcom_cc_map(pdev, &gcc_msm8996_desc);
@@ -3680,12 +3680,6 @@ static int gcc_msm8996_probe(struct platform_device *pdev)
         */
        regmap_update_bits(regmap, 0x52008, BIT(21), BIT(21));
 
-       for (i = 0; i < ARRAY_SIZE(gcc_msm8996_hws); i++) {
-               ret = devm_clk_hw_register(dev, gcc_msm8996_hws[i]);
-               if (ret)
-                       return ret;
-       }
-
        return qcom_cc_really_probe(pdev, &gcc_msm8996_desc, regmap);
 }
 
index 1b77939..c240fba 100644 (file)
@@ -1112,6 +1112,7 @@ static struct clk_rcg2 ufs_axi_clk_src = {
 
 static const struct freq_tbl ftbl_usb30_master_clk_src[] = {
        F(19200000, P_XO, 1, 0, 0),
+       F(60000000, P_GPLL0_OUT_MAIN, 10, 0, 0),
        F(120000000, P_GPLL0_OUT_MAIN, 5, 0, 0),
        F(150000000, P_GPLL0_OUT_MAIN, 4, 0, 0),
        { }
@@ -1189,6 +1190,7 @@ static struct clk_branch gcc_aggre1_ufs_axi_clk = {
                                "ufs_axi_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1206,6 +1208,7 @@ static struct clk_branch gcc_aggre1_usb3_axi_clk = {
                                "usb30_master_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1288,6 +1291,7 @@ static struct clk_branch gcc_blsp1_qup1_i2c_apps_clk = {
                                "blsp1_qup1_i2c_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1305,6 +1309,7 @@ static struct clk_branch gcc_blsp1_qup1_spi_apps_clk = {
                                "blsp1_qup1_spi_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1322,6 +1327,7 @@ static struct clk_branch gcc_blsp1_qup2_i2c_apps_clk = {
                                "blsp1_qup2_i2c_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1339,6 +1345,7 @@ static struct clk_branch gcc_blsp1_qup2_spi_apps_clk = {
                                "blsp1_qup2_spi_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1356,6 +1363,7 @@ static struct clk_branch gcc_blsp1_qup3_i2c_apps_clk = {
                                "blsp1_qup3_i2c_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1373,6 +1381,7 @@ static struct clk_branch gcc_blsp1_qup3_spi_apps_clk = {
                                "blsp1_qup3_spi_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1390,6 +1399,7 @@ static struct clk_branch gcc_blsp1_qup4_i2c_apps_clk = {
                                "blsp1_qup4_i2c_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1407,6 +1417,7 @@ static struct clk_branch gcc_blsp1_qup4_spi_apps_clk = {
                                "blsp1_qup4_spi_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1424,6 +1435,7 @@ static struct clk_branch gcc_blsp1_qup5_i2c_apps_clk = {
                                "blsp1_qup5_i2c_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1441,6 +1453,7 @@ static struct clk_branch gcc_blsp1_qup5_spi_apps_clk = {
                                "blsp1_qup5_spi_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1458,6 +1471,7 @@ static struct clk_branch gcc_blsp1_qup6_i2c_apps_clk = {
                                "blsp1_qup6_i2c_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1475,6 +1489,7 @@ static struct clk_branch gcc_blsp1_qup6_spi_apps_clk = {
                                "blsp1_qup6_spi_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1505,6 +1520,7 @@ static struct clk_branch gcc_blsp1_uart1_apps_clk = {
                                "blsp1_uart1_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1522,6 +1538,7 @@ static struct clk_branch gcc_blsp1_uart2_apps_clk = {
                                "blsp1_uart2_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1539,6 +1556,7 @@ static struct clk_branch gcc_blsp1_uart3_apps_clk = {
                                "blsp1_uart3_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1569,6 +1587,7 @@ static struct clk_branch gcc_blsp2_qup1_i2c_apps_clk = {
                                "blsp2_qup1_i2c_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1586,6 +1605,7 @@ static struct clk_branch gcc_blsp2_qup1_spi_apps_clk = {
                                "blsp2_qup1_spi_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1603,6 +1623,7 @@ static struct clk_branch gcc_blsp2_qup2_i2c_apps_clk = {
                                "blsp2_qup2_i2c_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1620,6 +1641,7 @@ static struct clk_branch gcc_blsp2_qup2_spi_apps_clk = {
                                "blsp2_qup2_spi_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1637,6 +1659,7 @@ static struct clk_branch gcc_blsp2_qup3_i2c_apps_clk = {
                                "blsp2_qup3_i2c_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1654,6 +1677,7 @@ static struct clk_branch gcc_blsp2_qup3_spi_apps_clk = {
                                "blsp2_qup3_spi_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1671,6 +1695,7 @@ static struct clk_branch gcc_blsp2_qup4_i2c_apps_clk = {
                                "blsp2_qup4_i2c_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1688,6 +1713,7 @@ static struct clk_branch gcc_blsp2_qup4_spi_apps_clk = {
                                "blsp2_qup4_spi_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1705,6 +1731,7 @@ static struct clk_branch gcc_blsp2_qup5_i2c_apps_clk = {
                                "blsp2_qup5_i2c_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1722,6 +1749,7 @@ static struct clk_branch gcc_blsp2_qup5_spi_apps_clk = {
                                "blsp2_qup5_spi_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1739,6 +1767,7 @@ static struct clk_branch gcc_blsp2_qup6_i2c_apps_clk = {
                                "blsp2_qup6_i2c_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1756,6 +1785,7 @@ static struct clk_branch gcc_blsp2_qup6_spi_apps_clk = {
                                "blsp2_qup6_spi_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1786,6 +1816,7 @@ static struct clk_branch gcc_blsp2_uart1_apps_clk = {
                                "blsp2_uart1_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1803,6 +1834,7 @@ static struct clk_branch gcc_blsp2_uart2_apps_clk = {
                                "blsp2_uart2_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1820,6 +1852,7 @@ static struct clk_branch gcc_blsp2_uart3_apps_clk = {
                                "blsp2_uart3_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1837,6 +1870,7 @@ static struct clk_branch gcc_cfg_noc_usb3_axi_clk = {
                                "usb30_master_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1854,6 +1888,7 @@ static struct clk_branch gcc_gp1_clk = {
                                "gp1_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1871,6 +1906,7 @@ static struct clk_branch gcc_gp2_clk = {
                                "gp2_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1888,6 +1924,7 @@ static struct clk_branch gcc_gp3_clk = {
                                "gp3_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1957,6 +1994,7 @@ static struct clk_branch gcc_hmss_ahb_clk = {
                                "hmss_ahb_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1987,6 +2025,7 @@ static struct clk_branch gcc_hmss_rbcpr_clk = {
                                "hmss_rbcpr_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -2088,6 +2127,7 @@ static struct clk_branch gcc_pcie_0_aux_clk = {
                                "pcie_aux_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -2157,6 +2197,7 @@ static struct clk_branch gcc_pcie_phy_aux_clk = {
                                "pcie_aux_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -2174,6 +2215,7 @@ static struct clk_branch gcc_pdm2_clk = {
                                "pdm2_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -2243,6 +2285,7 @@ static struct clk_branch gcc_sdcc2_apps_clk = {
                                "sdcc2_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -2273,6 +2316,7 @@ static struct clk_branch gcc_sdcc4_apps_clk = {
                                "sdcc4_apps_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -2316,6 +2360,7 @@ static struct clk_branch gcc_tsif_ref_clk = {
                                "tsif_ref_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -2346,6 +2391,7 @@ static struct clk_branch gcc_ufs_axi_clk = {
                                "ufs_axi_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -2441,6 +2487,7 @@ static struct clk_branch gcc_usb30_master_clk = {
                                "usb30_master_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -2458,6 +2505,7 @@ static struct clk_branch gcc_usb30_mock_utmi_clk = {
                                "usb30_mock_utmi_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -2488,6 +2536,7 @@ static struct clk_branch gcc_usb3_phy_aux_clk = {
                                "usb3_phy_aux_clk_src",
                        },
                        .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -2495,7 +2544,7 @@ static struct clk_branch gcc_usb3_phy_aux_clk = {
 
 static struct clk_branch gcc_usb3_phy_pipe_clk = {
        .halt_reg = 0x50004,
-       .halt_check = BRANCH_HALT,
+       .halt_check = BRANCH_HALT_SKIP,
        .clkr = {
                .enable_reg = 0x50004,
                .enable_mask = BIT(0),
@@ -2910,6 +2959,10 @@ static const struct regmap_config gcc_msm8998_regmap_config = {
        .fast_io        = true,
 };
 
+static struct clk_hw *gcc_msm8998_hws[] = {
+       &xo.hw,
+};
+
 static const struct qcom_cc_desc gcc_msm8998_desc = {
        .config = &gcc_msm8998_regmap_config,
        .clks = gcc_msm8998_clocks,
@@ -2918,6 +2971,8 @@ static const struct qcom_cc_desc gcc_msm8998_desc = {
        .num_resets = ARRAY_SIZE(gcc_msm8998_resets),
        .gdscs = gcc_msm8998_gdscs,
        .num_gdscs = ARRAY_SIZE(gcc_msm8998_gdscs),
+       .clk_hws = gcc_msm8998_hws,
+       .num_clk_hws = ARRAY_SIZE(gcc_msm8998_hws),
 };
 
 static int gcc_msm8998_probe(struct platform_device *pdev)
@@ -2937,10 +2992,6 @@ static int gcc_msm8998_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       ret = devm_clk_hw_register(&pdev->dev, &xo.hw);
-       if (ret)
-               return ret;
-
        return qcom_cc_really_probe(pdev, &gcc_msm8998_desc, regmap);
 }
 
index 64da032..5a62f64 100644 (file)
@@ -678,6 +678,7 @@ static struct clk_rcg2 blsp1_uart3_apps_clk_src = {
        .cmd_rcgr = 0x4014,
        .mnd_width = 16,
        .hid_width = 5,
+       .cfg_off = 0x20,
        .parent_map = gcc_parent_map_0,
        .freq_tbl = ftbl_blsp1_uart0_apps_clk_src,
        .clkr.hw.init = &(struct clk_init_data){
@@ -2692,6 +2693,8 @@ static const struct qcom_cc_desc gcc_qcs404_desc = {
        .num_clks = ARRAY_SIZE(gcc_qcs404_clocks),
        .resets = gcc_qcs404_resets,
        .num_resets = ARRAY_SIZE(gcc_qcs404_resets),
+       .clk_hws = gcc_qcs404_hws,
+       .num_clk_hws = ARRAY_SIZE(gcc_qcs404_hws),
 };
 
 static const struct of_device_id gcc_qcs404_match_table[] = {
@@ -2703,7 +2706,6 @@ MODULE_DEVICE_TABLE(of, gcc_qcs404_match_table);
 static int gcc_qcs404_probe(struct platform_device *pdev)
 {
        struct regmap *regmap;
-       int ret, i;
 
        regmap = qcom_cc_map(pdev, &gcc_qcs404_desc);
        if (IS_ERR(regmap))
@@ -2711,12 +2713,6 @@ static int gcc_qcs404_probe(struct platform_device *pdev)
 
        clk_alpha_pll_configure(&gpll3_out_main, regmap, &gpll3_config);
 
-       for (i = 0; i < ARRAY_SIZE(gcc_qcs404_hws); i++) {
-               ret = devm_clk_hw_register(&pdev->dev, gcc_qcs404_hws[i]);
-               if (ret)
-                       return ret;
-       }
-
        return qcom_cc_really_probe(pdev, &gcc_qcs404_desc, regmap);
 }
 
index ba239ea..8827db2 100644 (file)
@@ -2420,6 +2420,8 @@ static const struct qcom_cc_desc gcc_sdm660_desc = {
        .num_resets = ARRAY_SIZE(gcc_sdm660_resets),
        .gdscs = gcc_sdm660_gdscs,
        .num_gdscs = ARRAY_SIZE(gcc_sdm660_gdscs),
+       .clk_hws = gcc_sdm660_hws,
+       .num_clk_hws = ARRAY_SIZE(gcc_sdm660_hws),
 };
 
 static const struct of_device_id gcc_sdm660_match_table[] = {
@@ -2431,7 +2433,7 @@ MODULE_DEVICE_TABLE(of, gcc_sdm660_match_table);
 
 static int gcc_sdm660_probe(struct platform_device *pdev)
 {
-       int i, ret;
+       int ret;
        struct regmap *regmap;
 
        regmap = qcom_cc_map(pdev, &gcc_sdm660_desc);
@@ -2446,13 +2448,6 @@ static int gcc_sdm660_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       /* Register the hws */
-       for (i = 0; i < ARRAY_SIZE(gcc_sdm660_hws); i++) {
-               ret = devm_clk_hw_register(&pdev->dev, gcc_sdm660_hws[i]);
-               if (ret)
-                       return ret;
-       }
-
        return qcom_cc_really_probe(pdev, &gcc_sdm660_desc, regmap);
 }
 
index c782e62..7131dcf 100644 (file)
@@ -115,8 +115,8 @@ static const char * const gcc_parent_names_6[] = {
        "core_bi_pll_test_se",
 };
 
-static const char * const gcc_parent_names_7[] = {
-       "bi_tcxo",
+static const char * const gcc_parent_names_7_ao[] = {
+       "bi_tcxo_ao",
        "gpll0",
        "gpll0_out_even",
        "core_bi_pll_test_se",
@@ -128,6 +128,12 @@ static const char * const gcc_parent_names_8[] = {
        "core_bi_pll_test_se",
 };
 
+static const char * const gcc_parent_names_8_ao[] = {
+       "bi_tcxo_ao",
+       "gpll0",
+       "core_bi_pll_test_se",
+};
+
 static const struct parent_map gcc_parent_map_10[] = {
        { P_BI_TCXO, 0 },
        { P_GPLL0_OUT_MAIN, 1 },
@@ -210,7 +216,7 @@ static struct clk_rcg2 gcc_cpuss_ahb_clk_src = {
        .freq_tbl = ftbl_gcc_cpuss_ahb_clk_src,
        .clkr.hw.init = &(struct clk_init_data){
                .name = "gcc_cpuss_ahb_clk_src",
-               .parent_names = gcc_parent_names_7,
+               .parent_names = gcc_parent_names_7_ao,
                .num_parents = 4,
                .ops = &clk_rcg2_ops,
        },
@@ -229,7 +235,7 @@ static struct clk_rcg2 gcc_cpuss_rbcpr_clk_src = {
        .freq_tbl = ftbl_gcc_cpuss_rbcpr_clk_src,
        .clkr.hw.init = &(struct clk_init_data){
                .name = "gcc_cpuss_rbcpr_clk_src",
-               .parent_names = gcc_parent_names_8,
+               .parent_names = gcc_parent_names_8_ao,
                .num_parents = 3,
                .ops = &clk_rcg2_ops,
        },
@@ -1697,6 +1703,9 @@ static struct clk_branch gcc_pcie_0_pipe_clk = {
                .enable_mask = BIT(4),
                .hw.init = &(struct clk_init_data){
                        .name = "gcc_pcie_0_pipe_clk",
+                       .parent_names = (const char *[]){ "pcie_0_pipe_clk" },
+                       .num_parents = 1,
+                       .flags = CLK_SET_RATE_PARENT,
                        .ops = &clk_branch2_ops,
                },
        },
@@ -1796,6 +1805,8 @@ static struct clk_branch gcc_pcie_1_pipe_clk = {
                .enable_mask = BIT(30),
                .hw.init = &(struct clk_init_data){
                        .name = "gcc_pcie_1_pipe_clk",
+                       .parent_names = (const char *[]){ "pcie_1_pipe_clk" },
+                       .num_parents = 1,
                        .ops = &clk_branch2_ops,
                },
        },
index 7d4ee10..7235510 100644 (file)
@@ -3347,6 +3347,8 @@ static const struct qcom_cc_desc mmcc_msm8996_desc = {
        .num_resets = ARRAY_SIZE(mmcc_msm8996_resets),
        .gdscs = mmcc_msm8996_gdscs,
        .num_gdscs = ARRAY_SIZE(mmcc_msm8996_gdscs),
+       .clk_hws = mmcc_msm8996_hws,
+       .num_clk_hws = ARRAY_SIZE(mmcc_msm8996_hws),
 };
 
 static const struct of_device_id mmcc_msm8996_match_table[] = {
@@ -3357,8 +3359,6 @@ MODULE_DEVICE_TABLE(of, mmcc_msm8996_match_table);
 
 static int mmcc_msm8996_probe(struct platform_device *pdev)
 {
-       struct device *dev = &pdev->dev;
-       int i, ret;
        struct regmap *regmap;
 
        regmap = qcom_cc_map(pdev, &mmcc_msm8996_desc);
@@ -3370,12 +3370,6 @@ static int mmcc_msm8996_probe(struct platform_device *pdev)
        /* Disable the NoC FSM for mmss_mmagic_cfg_ahb_clk */
        regmap_update_bits(regmap, 0x5054, BIT(15), 0);
 
-       for (i = 0; i < ARRAY_SIZE(mmcc_msm8996_hws); i++) {
-               ret = devm_clk_hw_register(dev, mmcc_msm8996_hws[i]);
-               if (ret)
-                       return ret;
-       }
-
        return qcom_cc_really_probe(pdev, &mmcc_msm8996_desc, regmap);
 }
 
index 10e8525..4d92b27 100644 (file)
@@ -21,7 +21,7 @@
 
 enum clk_ids {
        /* Core Clock Outputs exported to DT */
-       LAST_DT_CORE_CLK = R8A774A1_CLK_OSC,
+       LAST_DT_CORE_CLK = R8A774A1_CLK_CANFD,
 
        /* External Input Clocks */
        CLK_EXTAL,
@@ -102,6 +102,7 @@ static const struct cpg_core_clk r8a774a1_core_clks[] __initconst = {
        DEF_FIXED("cp",         R8A774A1_CLK_CP,    CLK_EXTAL,      2, 1),
        DEF_FIXED("cpex",       R8A774A1_CLK_CPEX,  CLK_EXTAL,      2, 1),
 
+       DEF_DIV6P1("canfd",     R8A774A1_CLK_CANFD, CLK_PLL1_DIV4, 0x244),
        DEF_DIV6P1("csi0",      R8A774A1_CLK_CSI0,  CLK_PLL1_DIV4, 0x00c),
        DEF_DIV6P1("mso",       R8A774A1_CLK_MSO,   CLK_PLL1_DIV4, 0x014),
        DEF_DIV6P1("hdmi",      R8A774A1_CLK_HDMI,  CLK_PLL1_DIV4, 0x250),
@@ -191,6 +192,7 @@ static const struct mssr_mod_clk r8a774a1_mod_clks[] __initconst = {
        DEF_MOD("gpio2",                 910,   R8A774A1_CLK_S3D4),
        DEF_MOD("gpio1",                 911,   R8A774A1_CLK_S3D4),
        DEF_MOD("gpio0",                 912,   R8A774A1_CLK_S3D4),
+       DEF_MOD("can-fd",                914,   R8A774A1_CLK_S3D2),
        DEF_MOD("can-if1",               915,   R8A774A1_CLK_S3D4),
        DEF_MOD("can-if0",               916,   R8A774A1_CLK_S3D4),
        DEF_MOD("i2c6",                  918,   R8A774A1_CLK_S0D6),
index 10b9689..34e274f 100644 (file)
@@ -22,7 +22,7 @@
 
 enum clk_ids {
        /* Core Clock Outputs exported to DT */
-       LAST_DT_CORE_CLK = R8A774C0_CLK_CPEX,
+       LAST_DT_CORE_CLK = R8A774C0_CLK_CANFD,
 
        /* External Input Clocks */
        CLK_EXTAL,
@@ -33,6 +33,7 @@ enum clk_ids {
        CLK_PLL1,
        CLK_PLL3,
        CLK_PLL0D4,
+       CLK_PLL0D6,
        CLK_PLL0D8,
        CLK_PLL0D20,
        CLK_PLL0D24,
@@ -61,6 +62,7 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = {
 
        DEF_FIXED(".pll0",     CLK_PLL0,           CLK_MAIN,       1, 100),
        DEF_FIXED(".pll0d4",   CLK_PLL0D4,         CLK_PLL0,       4, 1),
+       DEF_FIXED(".pll0d6",   CLK_PLL0D6,         CLK_PLL0,       6, 1),
        DEF_FIXED(".pll0d8",   CLK_PLL0D8,         CLK_PLL0,       8, 1),
        DEF_FIXED(".pll0d20",  CLK_PLL0D20,        CLK_PLL0,      20, 1),
        DEF_FIXED(".pll0d24",  CLK_PLL0D24,        CLK_PLL0,      24, 1),
@@ -112,6 +114,7 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = {
        DEF_GEN3_PE("s3d2c",   R8A774C0_CLK_S3D2C, CLK_S3, 2, CLK_PE, 2),
        DEF_GEN3_PE("s3d4c",   R8A774C0_CLK_S3D4C, CLK_S3, 4, CLK_PE, 4),
 
+       DEF_DIV6P1("canfd",    R8A774C0_CLK_CANFD, CLK_PLL0D6, 0x244),
        DEF_DIV6P1("csi0",     R8A774C0_CLK_CSI0,  CLK_PLL1D2, 0x00c),
        DEF_DIV6P1("mso",      R8A774C0_CLK_MSO,   CLK_PLL1D2, 0x014),
 
@@ -119,6 +122,11 @@ static const struct cpg_core_clk r8a774c0_core_clks[] __initconst = {
 };
 
 static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = {
+       DEF_MOD("tmu4",                  121,   R8A774C0_CLK_S0D6C),
+       DEF_MOD("tmu3",                  122,   R8A774C0_CLK_S3D2C),
+       DEF_MOD("tmu2",                  123,   R8A774C0_CLK_S3D2C),
+       DEF_MOD("tmu1",                  124,   R8A774C0_CLK_S3D2C),
+       DEF_MOD("tmu0",                  125,   R8A774C0_CLK_CP),
        DEF_MOD("scif5",                 202,   R8A774C0_CLK_S3D4C),
        DEF_MOD("scif4",                 203,   R8A774C0_CLK_S3D4C),
        DEF_MOD("scif3",                 204,   R8A774C0_CLK_S3D4C),
@@ -172,8 +180,8 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = {
        DEF_MOD("ehci0",                 703,   R8A774C0_CLK_S3D4),
        DEF_MOD("hsusb",                 704,   R8A774C0_CLK_S3D4),
        DEF_MOD("csi40",                 716,   R8A774C0_CLK_CSI0),
-       DEF_MOD("du1",                   723,   R8A774C0_CLK_S2D1),
-       DEF_MOD("du0",                   724,   R8A774C0_CLK_S2D1),
+       DEF_MOD("du1",                   723,   R8A774C0_CLK_S1D1),
+       DEF_MOD("du0",                   724,   R8A774C0_CLK_S1D1),
        DEF_MOD("lvds",                  727,   R8A774C0_CLK_S2D1),
 
        DEF_MOD("vin5",                  806,   R8A774C0_CLK_S1D2),
@@ -187,6 +195,7 @@ static const struct mssr_mod_clk r8a774c0_mod_clks[] __initconst = {
        DEF_MOD("gpio2",                 910,   R8A774C0_CLK_S3D4),
        DEF_MOD("gpio1",                 911,   R8A774C0_CLK_S3D4),
        DEF_MOD("gpio0",                 912,   R8A774C0_CLK_S3D4),
+       DEF_MOD("can-fd",                914,   R8A774C0_CLK_S3D2),
        DEF_MOD("can-if1",               915,   R8A774C0_CLK_S3D4),
        DEF_MOD("can-if0",               916,   R8A774C0_CLK_S3D4),
        DEF_MOD("i2c6",                  918,   R8A774C0_CLK_S3D2),
index 25a3083..f9e07fc 100644 (file)
@@ -41,6 +41,7 @@ enum clk_ids {
        CLK_S2,
        CLK_S3,
        CLK_SDSRC,
+       CLK_RPCSRC,
        CLK_OCO,
 
        /* Module Clocks */
@@ -65,8 +66,14 @@ static const struct cpg_core_clk r8a77980_core_clks[] __initconst = {
        DEF_FIXED(".s2",        CLK_S2,            CLK_PLL1_DIV2,  4, 1),
        DEF_FIXED(".s3",        CLK_S3,            CLK_PLL1_DIV2,  6, 1),
        DEF_FIXED(".sdsrc",     CLK_SDSRC,         CLK_PLL1_DIV2,  2, 1),
+       DEF_BASE(".rpcsrc",     CLK_RPCSRC, CLK_TYPE_GEN3_RPCSRC, CLK_PLL1),
        DEF_RATE(".oco",        CLK_OCO,           32768),
 
+       DEF_BASE("rpc",         R8A77980_CLK_RPC, CLK_TYPE_GEN3_RPC,
+                CLK_RPCSRC),
+       DEF_BASE("rpcd2",       R8A77980_CLK_RPCD2, CLK_TYPE_GEN3_RPCD2,
+                R8A77980_CLK_RPC),
+
        /* Core Clock Outputs */
        DEF_FIXED("ztr",        R8A77980_CLK_ZTR,   CLK_PLL1_DIV2,  6, 1),
        DEF_FIXED("ztrd2",      R8A77980_CLK_ZTRD2, CLK_PLL1_DIV2, 12, 1),
@@ -164,6 +171,7 @@ static const struct mssr_mod_clk r8a77980_mod_clks[] __initconst = {
        DEF_MOD("gpio1",                 911,   R8A77980_CLK_CP),
        DEF_MOD("gpio0",                 912,   R8A77980_CLK_CP),
        DEF_MOD("can-fd",                914,   R8A77980_CLK_S3D2),
+       DEF_MOD("rpc-if",                917,   R8A77980_CLK_RPC),
        DEF_MOD("i2c4",                  927,   R8A77980_CLK_S0D6),
        DEF_MOD("i2c3",                  928,   R8A77980_CLK_S0D6),
        DEF_MOD("i2c2",                  929,   R8A77980_CLK_S3D2),
index be2ccbd..9a8071a 100644 (file)
 
 #define CPG_RCKCR_CKSEL        BIT(15) /* RCLK Clock Source Select */
 
+static spinlock_t cpg_lock;
+
+static void cpg_reg_modify(void __iomem *reg, u32 clear, u32 set)
+{
+       unsigned long flags;
+       u32 val;
+
+       spin_lock_irqsave(&cpg_lock, flags);
+       val = readl(reg);
+       val &= ~clear;
+       val |= set;
+       writel(val, reg);
+       spin_unlock_irqrestore(&cpg_lock, flags);
+};
+
 struct cpg_simple_notifier {
        struct notifier_block nb;
        void __iomem *reg;
@@ -118,7 +133,6 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
        struct cpg_z_clk *zclk = to_z_clk(hw);
        unsigned int mult;
        unsigned int i;
-       u32 val, kick;
 
        /* Factor of 2 is for fixed divider */
        mult = DIV_ROUND_CLOSEST_ULL(rate * 32ULL * 2, parent_rate);
@@ -127,17 +141,14 @@ static int cpg_z_clk_set_rate(struct clk_hw *hw, unsigned long rate,
        if (readl(zclk->kick_reg) & CPG_FRQCRB_KICK)
                return -EBUSY;
 
-       val = readl(zclk->reg) & ~zclk->mask;
-       val |= ((32 - mult) << __ffs(zclk->mask)) & zclk->mask;
-       writel(val, zclk->reg);
+       cpg_reg_modify(zclk->reg, zclk->mask,
+                      ((32 - mult) << __ffs(zclk->mask)) & zclk->mask);
 
        /*
         * Set KICK bit in FRQCRB to update hardware setting and wait for
         * clock change completion.
         */
-       kick = readl(zclk->kick_reg);
-       kick |= CPG_FRQCRB_KICK;
-       writel(kick, zclk->kick_reg);
+       cpg_reg_modify(zclk->kick_reg, 0, CPG_FRQCRB_KICK);
 
        /*
         * Note: There is no HW information about the worst case latency.
@@ -266,12 +277,10 @@ static const struct sd_div_table cpg_sd_div_table[] = {
 static int cpg_sd_clock_enable(struct clk_hw *hw)
 {
        struct sd_clock *clock = to_sd_clock(hw);
-       u32 val = readl(clock->csn.reg);
-
-       val &= ~(CPG_SD_STP_MASK);
-       val |= clock->div_table[clock->cur_div_idx].val & CPG_SD_STP_MASK;
 
-       writel(val, clock->csn.reg);
+       cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK,
+                      clock->div_table[clock->cur_div_idx].val &
+                      CPG_SD_STP_MASK);
 
        return 0;
 }
@@ -280,7 +289,7 @@ static void cpg_sd_clock_disable(struct clk_hw *hw)
 {
        struct sd_clock *clock = to_sd_clock(hw);
 
-       writel(readl(clock->csn.reg) | CPG_SD_STP_MASK, clock->csn.reg);
+       cpg_reg_modify(clock->csn.reg, 0, CPG_SD_STP_MASK);
 }
 
 static int cpg_sd_clock_is_enabled(struct clk_hw *hw)
@@ -327,7 +336,6 @@ static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
 {
        struct sd_clock *clock = to_sd_clock(hw);
        unsigned int div = cpg_sd_clock_calc_div(clock, rate, parent_rate);
-       u32 val;
        unsigned int i;
 
        for (i = 0; i < clock->div_num; i++)
@@ -339,10 +347,9 @@ static int cpg_sd_clock_set_rate(struct clk_hw *hw, unsigned long rate,
 
        clock->cur_div_idx = i;
 
-       val = readl(clock->csn.reg);
-       val &= ~(CPG_SD_STP_MASK | CPG_SD_FC_MASK);
-       val |= clock->div_table[i].val & (CPG_SD_STP_MASK | CPG_SD_FC_MASK);
-       writel(val, clock->csn.reg);
+       cpg_reg_modify(clock->csn.reg, CPG_SD_STP_MASK | CPG_SD_FC_MASK,
+                      clock->div_table[i].val &
+                      (CPG_SD_STP_MASK | CPG_SD_FC_MASK));
 
        return 0;
 }
@@ -415,6 +422,92 @@ free_clock:
        return clk;
 }
 
+struct rpc_clock {
+       struct clk_divider div;
+       struct clk_gate gate;
+       /*
+        * One notifier covers both RPC and RPCD2 clocks as they are both
+        * controlled by the same RPCCKCR register...
+        */
+       struct cpg_simple_notifier csn;
+};
+
+static const struct clk_div_table cpg_rpcsrc_div_table[] = {
+       { 2, 5 }, { 3, 6 }, { 0, 0 },
+};
+
+static const struct clk_div_table cpg_rpc_div_table[] = {
+       { 1, 2 }, { 3, 4 }, { 5, 6 }, { 7, 8 }, { 0, 0 },
+};
+
+static struct clk * __init cpg_rpc_clk_register(const char *name,
+       void __iomem *base, const char *parent_name,
+       struct raw_notifier_head *notifiers)
+{
+       struct rpc_clock *rpc;
+       struct clk *clk;
+
+       rpc = kzalloc(sizeof(*rpc), GFP_KERNEL);
+       if (!rpc)
+               return ERR_PTR(-ENOMEM);
+
+       rpc->div.reg = base + CPG_RPCCKCR;
+       rpc->div.width = 3;
+       rpc->div.table = cpg_rpc_div_table;
+       rpc->div.lock = &cpg_lock;
+
+       rpc->gate.reg = base + CPG_RPCCKCR;
+       rpc->gate.bit_idx = 8;
+       rpc->gate.flags = CLK_GATE_SET_TO_DISABLE;
+       rpc->gate.lock = &cpg_lock;
+
+       rpc->csn.reg = base + CPG_RPCCKCR;
+
+       clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+                                    &rpc->div.hw,  &clk_divider_ops,
+                                    &rpc->gate.hw, &clk_gate_ops, 0);
+       if (IS_ERR(clk)) {
+               kfree(rpc);
+               return clk;
+       }
+
+       cpg_simple_notifier_register(notifiers, &rpc->csn);
+       return clk;
+}
+
+struct rpcd2_clock {
+       struct clk_fixed_factor fixed;
+       struct clk_gate gate;
+};
+
+static struct clk * __init cpg_rpcd2_clk_register(const char *name,
+                                                 void __iomem *base,
+                                                 const char *parent_name)
+{
+       struct rpcd2_clock *rpcd2;
+       struct clk *clk;
+
+       rpcd2 = kzalloc(sizeof(*rpcd2), GFP_KERNEL);
+       if (!rpcd2)
+               return ERR_PTR(-ENOMEM);
+
+       rpcd2->fixed.mult = 1;
+       rpcd2->fixed.div = 2;
+
+       rpcd2->gate.reg = base + CPG_RPCCKCR;
+       rpcd2->gate.bit_idx = 9;
+       rpcd2->gate.flags = CLK_GATE_SET_TO_DISABLE;
+       rpcd2->gate.lock = &cpg_lock;
+
+       clk = clk_register_composite(NULL, name, &parent_name, 1, NULL, NULL,
+                                    &rpcd2->fixed.hw, &clk_fixed_factor_ops,
+                                    &rpcd2->gate.hw, &clk_gate_ops, 0);
+       if (IS_ERR(clk))
+               kfree(rpcd2);
+
+       return clk;
+}
+
 
 static const struct rcar_gen3_cpg_pll_config *cpg_pll_config __initdata;
 static unsigned int cpg_clk_extalr __initdata;
@@ -593,6 +686,21 @@ struct clk * __init rcar_gen3_cpg_clk_register(struct device *dev,
                }
                break;
 
+       case CLK_TYPE_GEN3_RPCSRC:
+               return clk_register_divider_table(NULL, core->name,
+                                                 __clk_get_name(parent), 0,
+                                                 base + CPG_RPCCKCR, 3, 2, 0,
+                                                 cpg_rpcsrc_div_table,
+                                                 &cpg_lock);
+
+       case CLK_TYPE_GEN3_RPC:
+               return cpg_rpc_clk_register(core->name, base,
+                                           __clk_get_name(parent), notifiers);
+
+       case CLK_TYPE_GEN3_RPCD2:
+               return cpg_rpcd2_clk_register(core->name, base,
+                                             __clk_get_name(parent));
+
        default:
                return ERR_PTR(-EINVAL);
        }
@@ -613,5 +721,8 @@ int __init rcar_gen3_cpg_init(const struct rcar_gen3_cpg_pll_config *config,
        if (attr)
                cpg_quirks = (uintptr_t)attr->data;
        pr_debug("%s: mode = 0x%x quirks = 0x%x\n", __func__, mode, cpg_quirks);
+
+       spin_lock_init(&cpg_lock);
+
        return 0;
 }
index f4fb6cf..eac1b05 100644 (file)
@@ -23,6 +23,9 @@ enum rcar_gen3_clk_types {
        CLK_TYPE_GEN3_Z2,
        CLK_TYPE_GEN3_OSC,      /* OSC EXTAL predivider and fixed divider */
        CLK_TYPE_GEN3_RCKSEL,   /* Select parent/divider using RCKCR.CKSEL */
+       CLK_TYPE_GEN3_RPCSRC,
+       CLK_TYPE_GEN3_RPC,
+       CLK_TYPE_GEN3_RPCD2,
 
        /* SoC specific definitions start here */
        CLK_TYPE_GEN3_SOC_BASE,
@@ -57,6 +60,7 @@ struct rcar_gen3_cpg_pll_config {
        u8 osc_prediv;
 };
 
+#define CPG_RPCCKCR    0x238
 #define CPG_RCKCR      0x240
 
 struct clk *rcar_gen3_cpg_clk_register(struct device *dev,
index 59d4d46..54066e6 100644 (file)
@@ -1028,6 +1028,7 @@ static unsigned long __init exynos4_get_xom(void)
                        xom = readl(chipid_base + 8);
 
                iounmap(chipid_base);
+               of_node_put(np);
        }
 
        return xom;
index 9330628..8ae44b5 100644 (file)
@@ -136,15 +136,20 @@ static int __init exynos5_clk_register_subcmu(struct device *parent,
 {
        struct of_phandle_args genpdspec = { .np = pd_node };
        struct platform_device *pdev;
+       int ret;
+
+       pdev = platform_device_alloc("exynos5-subcmu", PLATFORM_DEVID_AUTO);
+       if (!pdev)
+               return -ENOMEM;
 
-       pdev = platform_device_alloc(info->pd_name, -1);
        pdev->dev.parent = parent;
-       pdev->driver_override = "exynos5-subcmu";
        platform_set_drvdata(pdev, (void *)info);
        of_genpd_add_device(&genpdspec, &pdev->dev);
-       platform_device_add(pdev);
+       ret = platform_device_add(pdev);
+       if (ret)
+               platform_device_put(pdev);
 
-       return 0;
+       return ret;
 }
 
 static int __init exynos5_clk_probe(struct platform_device *pdev)
index 751e2c4..dae1c96 100644 (file)
@@ -559,7 +559,7 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
        /* ENABLE_ACLK_TOP */
        GATE(CLK_ACLK_G3D_400, "aclk_g3d_400", "div_aclk_g3d_400",
                        ENABLE_ACLK_TOP, 30, CLK_IS_CRITICAL, 0),
-       GATE(CLK_ACLK_IMEM_SSX_266, "aclk_imem_ssx_266",
+       GATE(CLK_ACLK_IMEM_SSSX_266, "aclk_imem_sssx_266",
                        "div_aclk_imem_sssx_266", ENABLE_ACLK_TOP,
                        29, CLK_IGNORE_UNUSED, 0),
        GATE(CLK_ACLK_BUS0_400, "aclk_bus0_400", "div_aclk_bus0_400",
@@ -568,10 +568,10 @@ static const struct samsung_gate_clock top_gate_clks[] __initconst = {
        GATE(CLK_ACLK_BUS1_400, "aclk_bus1_400", "div_aclk_bus1_400",
                        ENABLE_ACLK_TOP, 25,
                        CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
-       GATE(CLK_ACLK_IMEM_200, "aclk_imem_200", "div_aclk_imem_266",
+       GATE(CLK_ACLK_IMEM_200, "aclk_imem_200", "div_aclk_imem_200",
                        ENABLE_ACLK_TOP, 24,
                        CLK_IS_CRITICAL | CLK_SET_RATE_PARENT, 0),
-       GATE(CLK_ACLK_IMEM_266, "aclk_imem_266", "div_aclk_imem_200",
+       GATE(CLK_ACLK_IMEM_266, "aclk_imem_266", "div_aclk_imem_266",
                        ENABLE_ACLK_TOP, 23,
                        CLK_IGNORE_UNUSED | CLK_SET_RATE_PARENT, 0),
        GATE(CLK_ACLK_PERIC_66, "aclk_peric_66", "div_aclk_peric_66_b",
@@ -5467,6 +5467,35 @@ static const struct samsung_cmu_info cam1_cmu_info __initconst = {
        .clk_name               = "aclk_cam1_400",
 };
 
+/*
+ * Register offset definitions for CMU_IMEM
+ */
+#define ENABLE_ACLK_IMEM_SLIMSSS               0x080c
+#define ENABLE_PCLK_IMEM_SLIMSSS               0x0908
+
+static const unsigned long imem_clk_regs[] __initconst = {
+       ENABLE_ACLK_IMEM_SLIMSSS,
+       ENABLE_PCLK_IMEM_SLIMSSS,
+};
+
+static const struct samsung_gate_clock imem_gate_clks[] __initconst = {
+       /* ENABLE_ACLK_IMEM_SLIMSSS */
+       GATE(CLK_ACLK_SLIMSSS, "aclk_slimsss", "aclk_imem_sssx_266",
+                       ENABLE_ACLK_IMEM_SLIMSSS, 0, CLK_IGNORE_UNUSED, 0),
+
+       /* ENABLE_PCLK_IMEM_SLIMSSS */
+       GATE(CLK_PCLK_SLIMSSS, "pclk_slimsss", "aclk_imem_200",
+                       ENABLE_PCLK_IMEM_SLIMSSS, 0, CLK_IGNORE_UNUSED, 0),
+};
+
+static const struct samsung_cmu_info imem_cmu_info __initconst = {
+       .gate_clks              = imem_gate_clks,
+       .nr_gate_clks           = ARRAY_SIZE(imem_gate_clks),
+       .nr_clk_ids             = IMEM_NR_CLK,
+       .clk_regs               = imem_clk_regs,
+       .nr_clk_regs            = ARRAY_SIZE(imem_clk_regs),
+       .clk_name               = "aclk_imem_200",
+};
 
 struct exynos5433_cmu_data {
        struct samsung_clk_reg_dump *clk_save;
@@ -5654,6 +5683,9 @@ static const struct of_device_id exynos5433_cmu_of_match[] = {
        }, {
                .compatible = "samsung,exynos5433-cmu-mscl",
                .data = &mscl_cmu_info,
+       }, {
+               .compatible = "samsung,exynos5433-cmu-imem",
+               .data = &imem_cmu_info,
        }, {
        },
 };
index 884067e..f38f0e2 100644 (file)
@@ -389,7 +389,7 @@ void __init s3c2443_common_clk_init(struct device_node *np, unsigned long xti_f,
                                ARRAY_SIZE(s3c2450_gates));
                samsung_clk_register_alias(ctx, s3c2450_aliases,
                                ARRAY_SIZE(s3c2450_aliases));
-               /* fall through, as s3c2450 extends the s3c2416 clocks */
+               /* fall through - as s3c2450 extends the s3c2416 clocks */
        case S3C2416:
                samsung_clk_register_div(ctx, s3c2416_dividers,
                                ARRAY_SIZE(s3c2416_dividers));
index aa7a6e6..73e0332 100644 (file)
@@ -176,8 +176,7 @@ static struct clk_ops gateclk_ops = {
        .set_parent = socfpga_clk_set_parent,
 };
 
-static void __init __socfpga_gate_init(struct device_node *node,
-       const struct clk_ops *ops)
+void __init socfpga_gate_init(struct device_node *node)
 {
        u32 clk_gate[2];
        u32 div_reg[3];
@@ -188,12 +187,17 @@ static void __init __socfpga_gate_init(struct device_node *node,
        const char *clk_name = node->name;
        const char *parent_name[SOCFPGA_MAX_PARENTS];
        struct clk_init_data init;
+       struct clk_ops *ops;
        int rc;
 
        socfpga_clk = kzalloc(sizeof(*socfpga_clk), GFP_KERNEL);
        if (WARN_ON(!socfpga_clk))
                return;
 
+       ops = kmemdup(&gateclk_ops, sizeof(gateclk_ops), GFP_KERNEL);
+       if (WARN_ON(!ops))
+               return;
+
        rc = of_property_read_u32_array(node, "clk-gate", clk_gate, 2);
        if (rc)
                clk_gate[0] = 0;
@@ -202,8 +206,8 @@ static void __init __socfpga_gate_init(struct device_node *node,
                socfpga_clk->hw.reg = clk_mgr_base_addr + clk_gate[0];
                socfpga_clk->hw.bit_idx = clk_gate[1];
 
-               gateclk_ops.enable = clk_gate_ops.enable;
-               gateclk_ops.disable = clk_gate_ops.disable;
+               ops->enable = clk_gate_ops.enable;
+               ops->disable = clk_gate_ops.disable;
        }
 
        rc = of_property_read_u32(node, "fixed-divider", &fixed_div);
@@ -234,6 +238,11 @@ static void __init __socfpga_gate_init(struct device_node *node,
        init.flags = 0;
 
        init.num_parents = of_clk_parent_fill(node, parent_name, SOCFPGA_MAX_PARENTS);
+       if (init.num_parents < 2) {
+               ops->get_parent = NULL;
+               ops->set_parent = NULL;
+       }
+
        init.parent_names = parent_name;
        socfpga_clk->hw.hw.init = &init;
 
@@ -246,8 +255,3 @@ static void __init __socfpga_gate_init(struct device_node *node,
        if (WARN_ON(rc))
                return;
 }
-
-void __init socfpga_gate_init(struct device_node *node)
-{
-       __socfpga_gate_init(node, &gateclk_ops);
-}
index 35fabe1..269467e 100644 (file)
@@ -95,6 +95,7 @@ static struct clk * __init __socfpga_pll_init(struct device_node *node,
 
        clkmgr_np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr");
        clk_mgr_a10_base_addr = of_iomap(clkmgr_np, 0);
+       of_node_put(clkmgr_np);
        BUG_ON(!clk_mgr_a10_base_addr);
        pll_clk->hw.reg = clk_mgr_a10_base_addr + reg;
 
index 2d5d8b4..c4d0b6f 100644 (file)
@@ -43,7 +43,7 @@ static unsigned long clk_pll_recalc_rate(struct clk_hw *hwclk,
        /* Read mdiv and fdiv from the fdbck register */
        reg = readl(socfpgaclk->hw.reg + 0x4);
        mdiv = (reg & SOCFPGA_PLL_MDIV_MASK) >> SOCFPGA_PLL_MDIV_SHIFT;
-       vco_freq = (unsigned long long)parent_rate * (mdiv + 6);
+       vco_freq = (unsigned long long)vco_freq * (mdiv + 6);
 
        return (unsigned long)vco_freq;
 }
index c7f4631..b4b44e9 100644 (file)
@@ -100,6 +100,7 @@ static __init struct clk *__socfpga_pll_init(struct device_node *node,
 
        clkmgr_np = of_find_compatible_node(NULL, NULL, "altr,clk-mgr");
        clk_mgr_base_addr = of_iomap(clkmgr_np, 0);
+       of_node_put(clkmgr_np);
        BUG_ON(!clk_mgr_base_addr);
        pll_clk->hw.reg = clk_mgr_base_addr + reg;
 
index 5b238fc..8281dfb 100644 (file)
 
 #include "stratix10-clk.h"
 
-static const char * const pll_mux[] = { "osc1", "cb_intosc_hs_div2_clk",
-                                       "f2s_free_clk",};
+static const char * const pll_mux[] = { "osc1", "cb-intosc-hs-div2-clk",
+                                       "f2s-free-clk",};
 static const char * const cntr_mux[] = { "main_pll", "periph_pll",
-                                        "osc1", "cb_intosc_hs_div2_clk",
-                                        "f2s_free_clk"};
-static const char * const boot_mux[] = { "osc1", "cb_intosc_hs_div2_clk",};
+                                        "osc1", "cb-intosc-hs-div2-clk",
+                                        "f2s-free-clk"};
+static const char * const boot_mux[] = { "osc1", "cb-intosc-hs-div2-clk",};
 
 static const char * const noc_free_mux[] = {"main_noc_base_clk",
                                            "peri_noc_base_clk",
-                                           "osc1", "cb_intosc_hs_div2_clk",
-                                           "f2s_free_clk"};
+                                           "osc1", "cb-intosc-hs-div2-clk",
+                                           "f2s-free-clk"};
 
 static const char * const emaca_free_mux[] = {"peri_emaca_clk", "boot_clk"};
 static const char * const emacb_free_mux[] = {"peri_emacb_clk", "boot_clk"};
@@ -33,14 +33,14 @@ static const char * const s2f_usr1_free_mux[] = {"peri_s2f_usr1_clk", "boot_clk"
 static const char * const psi_ref_free_mux[] = {"peri_psi_ref_clk", "boot_clk"};
 static const char * const mpu_mux[] = { "mpu_free_clk", "boot_clk",};
 
-static const char * const s2f_usr0_mux[] = {"f2s_free_clk", "boot_clk"};
+static const char * const s2f_usr0_mux[] = {"f2s-free-clk", "boot_clk"};
 static const char * const emac_mux[] = {"emaca_free_clk", "emacb_free_clk"};
 static const char * const noc_mux[] = {"noc_free_clk", "boot_clk"};
 
 static const char * const mpu_free_mux[] = {"main_mpu_base_clk",
                                            "peri_mpu_base_clk",
-                                           "osc1", "cb_intosc_hs_div2_clk",
-                                           "f2s_free_clk"};
+                                           "osc1", "cb-intosc-hs-div2-clk",
+                                           "f2s-free-clk"};
 
 /* clocks in AO (always on) controller */
 static const struct stratix10_pll_clock s10_pll_clks[] = {
index 3b97f60..609970c 100644 (file)
@@ -264,9 +264,9 @@ static SUNXI_CCU_GATE(ahb1_mmc1_clk,        "ahb1-mmc1",    "ahb1",
 static SUNXI_CCU_GATE(ahb1_mmc2_clk,   "ahb1-mmc2",    "ahb1",
                      0x060, BIT(10), 0);
 static SUNXI_CCU_GATE(ahb1_mmc3_clk,   "ahb1-mmc3",    "ahb1",
-                     0x060, BIT(12), 0);
+                     0x060, BIT(11), 0);
 static SUNXI_CCU_GATE(ahb1_nand1_clk,  "ahb1-nand1",   "ahb1",
-                     0x060, BIT(13), 0);
+                     0x060, BIT(12), 0);
 static SUNXI_CCU_GATE(ahb1_nand0_clk,  "ahb1-nand0",   "ahb1",
                      0x060, BIT(13), 0);
 static SUNXI_CCU_GATE(ahb1_sdram_clk,  "ahb1-sdram",   "ahb1",
index a4fa294..4b5f8f4 100644 (file)
@@ -144,7 +144,7 @@ static SUNXI_CCU_NKM_WITH_GATE_LOCK(pll_mipi_clk, "pll-mipi",
                                    8, 4,               /* N */
                                    4, 2,               /* K */
                                    0, 4,               /* M */
-                                   BIT(31),            /* gate */
+                                   BIT(31) | BIT(23) | BIT(22), /* gate */
                                    BIT(28),            /* lock */
                                    CLK_SET_RATE_UNGATE);
 
index 621b1cd..ac12f26 100644 (file)
@@ -542,7 +542,7 @@ static struct ccu_reset_map sun8i_v3s_ccu_resets[] = {
        [RST_BUS_OHCI0]         =  { 0x2c0, BIT(29) },
 
        [RST_BUS_VE]            =  { 0x2c4, BIT(0) },
-       [RST_BUS_TCON0]         =  { 0x2c4, BIT(3) },
+       [RST_BUS_TCON0]         =  { 0x2c4, BIT(4) },
        [RST_BUS_CSI]           =  { 0x2c4, BIT(8) },
        [RST_BUS_DE]            =  { 0x2c4, BIT(12) },
        [RST_BUS_DBG]           =  { 0x2c4, BIT(31) },
index 609e363..7ec752e 100644 (file)
@@ -1112,8 +1112,8 @@ static int attr_enable_set(void *data, u64 val)
 
        return val ? dfll_enable(td) : dfll_disable(td);
 }
-DEFINE_SIMPLE_ATTRIBUTE(enable_fops, attr_enable_get, attr_enable_set,
-                       "%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(enable_fops, attr_enable_get, attr_enable_set,
+                        "%llu\n");
 
 static int attr_lock_get(void *data, u64 *val)
 {
@@ -1129,8 +1129,7 @@ static int attr_lock_set(void *data, u64 val)
 
        return val ? dfll_lock(td) :  dfll_unlock(td);
 }
-DEFINE_SIMPLE_ATTRIBUTE(lock_fops, attr_lock_get, attr_lock_set,
-                       "%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(lock_fops, attr_lock_get, attr_lock_set, "%llu\n");
 
 static int attr_rate_get(void *data, u64 *val)
 {
@@ -1147,7 +1146,7 @@ static int attr_rate_set(void *data, u64 val)
 
        return dfll_request_rate(td, val);
 }
-DEFINE_SIMPLE_ATTRIBUTE(rate_fops, attr_rate_get, attr_rate_set, "%llu\n");
+DEFINE_DEBUGFS_ATTRIBUTE(rate_fops, attr_rate_get, attr_rate_set, "%llu\n");
 
 static int attr_registers_show(struct seq_file *s, void *data)
 {
@@ -1196,10 +1195,11 @@ static void dfll_debug_init(struct tegra_dfll *td)
        root = debugfs_create_dir("tegra_dfll_fcpu", NULL);
        td->debugfs_dir = root;
 
-       debugfs_create_file("enable", S_IRUGO | S_IWUSR, root, td, &enable_fops);
-       debugfs_create_file("lock", S_IRUGO, root, td, &lock_fops);
-       debugfs_create_file("rate", S_IRUGO, root, td, &rate_fops);
-       debugfs_create_file("registers", S_IRUGO, root, td, &attr_registers_fops);
+       debugfs_create_file_unsafe("enable", 0644, root, td,
+                                  &enable_fops);
+       debugfs_create_file_unsafe("lock", 0444, root, td, &lock_fops);
+       debugfs_create_file_unsafe("rate", 0444, root, td, &rate_fops);
+       debugfs_create_file("registers", 0444, root, td, &attr_registers_fops);
 }
 
 #else
index 269d359..edc31bb 100644 (file)
@@ -133,9 +133,11 @@ static int tegra124_dfll_fcpu_remove(struct platform_device *pdev)
        struct tegra_dfll_soc_data *soc;
 
        soc = tegra_dfll_unregister(pdev);
-       if (IS_ERR(soc))
+       if (IS_ERR(soc)) {
                dev_err(&pdev->dev, "failed to unregister DFLL: %ld\n",
                        PTR_ERR(soc));
+               return PTR_ERR(soc);
+       }
 
        tegra_cvb_remove_opp_table(soc->dev, soc->cvb, soc->max_freq);
 
index 688e403..0c21098 100644 (file)
@@ -614,7 +614,7 @@ static int ti_adpll_init_clkout(struct ti_adpll_data *d,
 
        init.name = child_name;
        init.ops = ops;
-       init.flags = CLK_IS_BASIC;
+       init.flags = 0;
        co->hw.init = &init;
        parent_names[0] = __clk_get_name(clk0);
        parent_names[1] = __clk_get_name(clk1);
index 222f68b..015a657 100644 (file)
@@ -165,7 +165,7 @@ static void __init omap_clk_register_apll(void *user,
 
        ad->clk_bypass = __clk_get_hw(clk);
 
-       clk = ti_clk_register(NULL, &clk_hw->hw, node->name);
+       clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, node->name);
        if (!IS_ERR(clk)) {
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
                kfree(clk_hw->hw.init->parent_names);
@@ -402,7 +402,7 @@ static void __init of_omap2_apll_setup(struct device_node *node)
        if (ret)
                goto cleanup;
 
-       clk = clk_register(NULL, &clk_hw->hw);
+       clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, node->name);
        if (!IS_ERR(clk)) {
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
                kfree(init);
index 7bb9afb..1cae226 100644 (file)
@@ -35,7 +35,44 @@ struct clk_ti_autoidle {
 #define AUTOIDLE_LOW           0x1
 
 static LIST_HEAD(autoidle_clks);
-static LIST_HEAD(clk_hw_omap_clocks);
+
+/*
+ * we have some non-atomic read/write
+ * operations behind it, so lets
+ * take one lock for handling autoidle
+ * of all clocks
+ */
+static DEFINE_SPINLOCK(autoidle_spinlock);
+
+static int _omap2_clk_deny_idle(struct clk_hw_omap *clk)
+{
+       if (clk->ops && clk->ops->deny_idle) {
+               unsigned long irqflags;
+
+               spin_lock_irqsave(&autoidle_spinlock, irqflags);
+               clk->autoidle_count++;
+               if (clk->autoidle_count == 1)
+                       clk->ops->deny_idle(clk);
+
+               spin_unlock_irqrestore(&autoidle_spinlock, irqflags);
+       }
+       return 0;
+}
+
+static int _omap2_clk_allow_idle(struct clk_hw_omap *clk)
+{
+       if (clk->ops && clk->ops->allow_idle) {
+               unsigned long irqflags;
+
+               spin_lock_irqsave(&autoidle_spinlock, irqflags);
+               clk->autoidle_count--;
+               if (clk->autoidle_count == 0)
+                       clk->ops->allow_idle(clk);
+
+               spin_unlock_irqrestore(&autoidle_spinlock, irqflags);
+       }
+       return 0;
+}
 
 /**
  * omap2_clk_deny_idle - disable autoidle on an OMAP clock
@@ -45,12 +82,15 @@ static LIST_HEAD(clk_hw_omap_clocks);
  */
 int omap2_clk_deny_idle(struct clk *clk)
 {
-       struct clk_hw_omap *c;
+       struct clk_hw *hw = __clk_get_hw(clk);
 
-       c = to_clk_hw_omap(__clk_get_hw(clk));
-       if (c->ops && c->ops->deny_idle)
-               c->ops->deny_idle(c);
-       return 0;
+       if (omap2_clk_is_hw_omap(hw)) {
+               struct clk_hw_omap *c = to_clk_hw_omap(hw);
+
+               return _omap2_clk_deny_idle(c);
+       }
+
+       return -EINVAL;
 }
 
 /**
@@ -61,12 +101,15 @@ int omap2_clk_deny_idle(struct clk *clk)
  */
 int omap2_clk_allow_idle(struct clk *clk)
 {
-       struct clk_hw_omap *c;
+       struct clk_hw *hw = __clk_get_hw(clk);
 
-       c = to_clk_hw_omap(__clk_get_hw(clk));
-       if (c->ops && c->ops->allow_idle)
-               c->ops->allow_idle(c);
-       return 0;
+       if (omap2_clk_is_hw_omap(hw)) {
+               struct clk_hw_omap *c = to_clk_hw_omap(hw);
+
+               return _omap2_clk_allow_idle(c);
+       }
+
+       return -EINVAL;
 }
 
 static void _allow_autoidle(struct clk_ti_autoidle *clk)
@@ -167,26 +210,6 @@ int __init of_ti_clk_autoidle_setup(struct device_node *node)
        return 0;
 }
 
-/**
- * omap2_init_clk_hw_omap_clocks - initialize an OMAP clock
- * @hw: struct clk_hw * to initialize
- *
- * Add an OMAP clock @clk to the internal list of OMAP clocks.  Used
- * temporarily for autoidle handling, until this support can be
- * integrated into the common clock framework code in some way.  No
- * return value.
- */
-void omap2_init_clk_hw_omap_clocks(struct clk_hw *hw)
-{
-       struct clk_hw_omap *c;
-
-       if (clk_hw_get_flags(hw) & CLK_IS_BASIC)
-               return;
-
-       c = to_clk_hw_omap(hw);
-       list_add(&c->node, &clk_hw_omap_clocks);
-}
-
 /**
  * omap2_clk_enable_autoidle_all - enable autoidle on all OMAP clocks that
  * support it
@@ -198,11 +221,11 @@ void omap2_init_clk_hw_omap_clocks(struct clk_hw *hw)
  */
 int omap2_clk_enable_autoidle_all(void)
 {
-       struct clk_hw_omap *c;
+       int ret;
 
-       list_for_each_entry(c, &clk_hw_omap_clocks, node)
-               if (c->ops && c->ops->allow_idle)
-                       c->ops->allow_idle(c);
+       ret = omap2_clk_for_each(_omap2_clk_allow_idle);
+       if (ret)
+               return ret;
 
        _clk_generic_allow_autoidle_all();
 
@@ -220,11 +243,11 @@ int omap2_clk_enable_autoidle_all(void)
  */
 int omap2_clk_disable_autoidle_all(void)
 {
-       struct clk_hw_omap *c;
+       int ret;
 
-       list_for_each_entry(c, &clk_hw_omap_clocks, node)
-               if (c->ops && c->ops->deny_idle)
-                       c->ops->deny_idle(c);
+       ret = omap2_clk_for_each(_omap2_clk_deny_idle);
+       if (ret)
+               return ret;
 
        _clk_generic_deny_autoidle_all();
 
index d0cd585..ff164a3 100644 (file)
@@ -31,6 +31,7 @@
 #undef pr_fmt
 #define pr_fmt(fmt) "%s: " fmt, __func__
 
+static LIST_HEAD(clk_hw_omap_clocks);
 struct ti_clk_ll_ops *ti_clk_ll_ops;
 static struct device_node *clocks_node_ptr[CLK_MAX_MEMMAPS];
 
@@ -191,9 +192,13 @@ void __init ti_dt_clocks_register(struct ti_dt_clk oclks[])
                        clkdev_add(&c->lk);
                } else {
                        if (num_args && !has_clkctrl_data) {
-                               if (of_find_compatible_node(NULL, NULL,
-                                                           "ti,clkctrl")) {
+                               struct device_node *np;
+
+                               np = of_find_compatible_node(NULL, NULL,
+                                                            "ti,clkctrl");
+                               if (np) {
                                        has_clkctrl_data = true;
+                                       of_node_put(np);
                                } else {
                                        clkctrl_nodes_missing = true;
 
@@ -517,3 +522,74 @@ struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
 
        return clk;
 }
+
+/**
+ * ti_clk_register_omap_hw - register a clk_hw_omap to the clock framework
+ * @dev: device for this clock
+ * @hw: hardware clock handle
+ * @con: connection ID for this clock
+ *
+ * Registers a clk_hw_omap clock to the clock framewor, adds a clock alias
+ * for it, and adds the list to the available clk_hw_omap type clocks.
+ * Returns a handle to the registered clock if successful, ERR_PTR value
+ * in failure.
+ */
+struct clk *ti_clk_register_omap_hw(struct device *dev, struct clk_hw *hw,
+                                   const char *con)
+{
+       struct clk *clk;
+       struct clk_hw_omap *oclk;
+
+       clk = ti_clk_register(dev, hw, con);
+       if (IS_ERR(clk))
+               return clk;
+
+       oclk = to_clk_hw_omap(hw);
+
+       list_add(&oclk->node, &clk_hw_omap_clocks);
+
+       return clk;
+}
+
+/**
+ * omap2_clk_for_each - call function for each registered clk_hw_omap
+ * @fn: pointer to a callback function
+ *
+ * Call @fn for each registered clk_hw_omap, passing @hw to each
+ * function.  @fn must return 0 for success or any other value for
+ * failure.  If @fn returns non-zero, the iteration across clocks
+ * will stop and the non-zero return value will be passed to the
+ * caller of omap2_clk_for_each().
+ */
+int omap2_clk_for_each(int (*fn)(struct clk_hw_omap *hw))
+{
+       int ret;
+       struct clk_hw_omap *hw;
+
+       list_for_each_entry(hw, &clk_hw_omap_clocks, node) {
+               ret = (*fn)(hw);
+               if (ret)
+                       break;
+       }
+
+       return ret;
+}
+
+/**
+ * omap2_clk_is_hw_omap - check if the provided clk_hw is OMAP clock
+ * @hw: clk_hw to check if it is an omap clock or not
+ *
+ * Checks if the provided clk_hw is OMAP clock or not. Returns true if
+ * it is, false otherwise.
+ */
+bool omap2_clk_is_hw_omap(struct clk_hw *hw)
+{
+       struct clk_hw_omap *oclk;
+
+       list_for_each_entry(oclk, &clk_hw_omap_clocks, node) {
+               if (&oclk->hw == hw)
+                       return true;
+       }
+
+       return false;
+}
index 40630eb..bf32d99 100644 (file)
@@ -276,7 +276,7 @@ _ti_clkctrl_clk_register(struct omap_clkctrl_provider *provider,
        init.parent_names = parents;
        init.num_parents = num_parents;
        init.ops = ops;
-       init.flags = CLK_IS_BASIC;
+       init.flags = 0;
 
        clk = ti_clk_register(NULL, clk_hw, init.name);
        if (IS_ERR_OR_NULL(clk)) {
index 9f312a2..1c0fac5 100644 (file)
@@ -203,6 +203,8 @@ typedef void (*ti_of_clk_init_cb_t)(void *, struct device_node *);
 
 struct clk *ti_clk_register(struct device *dev, struct clk_hw *hw,
                            const char *con);
+struct clk *ti_clk_register_omap_hw(struct device *dev, struct clk_hw *hw,
+                                   const char *con);
 int ti_clk_add_alias(struct device *dev, struct clk *clk, const char *con);
 void ti_clk_add_aliases(void);
 
@@ -221,7 +223,6 @@ int ti_clk_retry_init(struct device_node *node, void *user,
                      ti_of_clk_init_cb_t func);
 int ti_clk_add_component(struct device_node *node, struct clk_hw *hw, int type);
 
-void omap2_init_clk_hw_omap_clocks(struct clk_hw *hw);
 int of_ti_clk_autoidle_setup(struct device_node *node);
 void omap2_clk_enable_init_clocks(const char **clk_names, u8 num_clocks);
 
@@ -301,6 +302,8 @@ long omap4_dpll_regm4xen_round_rate(struct clk_hw *hw,
                                    unsigned long *parent_rate);
 int omap4_dpll_regm4xen_determine_rate(struct clk_hw *hw,
                                       struct clk_rate_request *req);
+int omap2_clk_for_each(int (*fn)(struct clk_hw_omap *hw));
+bool omap2_clk_is_hw_omap(struct clk_hw *hw);
 
 extern struct ti_clk_ll_ops *ti_clk_ll_ops;
 
index 07a8051..423a99b 100644 (file)
@@ -143,7 +143,7 @@ static void __init of_ti_clockdomain_setup(struct device_node *node)
                        continue;
                }
                clk_hw = __clk_get_hw(clk);
-               if (clk_hw_get_flags(clk_hw) & CLK_IS_BASIC) {
+               if (!omap2_clk_is_hw_omap(clk_hw)) {
                        pr_warn("can't setup clkdm for basic clk %s\n",
                                __clk_get_name(clk));
                        continue;
index 8d77090..4786e0e 100644 (file)
@@ -336,7 +336,7 @@ static struct clk *_register_divider(struct device *dev, const char *name,
 
        init.name = name;
        init.ops = &ti_clk_divider_ops;
-       init.flags = flags | CLK_IS_BASIC;
+       init.flags = flags;
        init.parent_names = (parent_name ? &parent_name : NULL);
        init.num_parents = (parent_name ? 1 : 0);
 
@@ -403,8 +403,10 @@ int ti_clk_parse_divider_data(int *div_table, int num_dividers, int max_div,
        num_dividers = i;
 
        tmp = kcalloc(valid_div + 1, sizeof(*tmp), GFP_KERNEL);
-       if (!tmp)
+       if (!tmp) {
+               *table = ERR_PTR(-ENOMEM);
                return -ENOMEM;
+       }
 
        valid_div = 0;
        *width = 0;
@@ -439,6 +441,7 @@ struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
 {
        struct clk_omap_divider *div;
        struct clk_omap_reg *reg;
+       int ret;
 
        if (!setup)
                return NULL;
@@ -458,6 +461,12 @@ struct clk_hw *ti_clk_build_component_div(struct ti_clk_divider *setup)
                div->flags |= CLK_DIVIDER_POWER_OF_TWO;
 
        div->table = _get_div_table_from_setup(setup, &div->width);
+       if (IS_ERR(div->table)) {
+               ret = PTR_ERR(div->table);
+               kfree(div);
+               return ERR_PTR(ret);
+       }
+
 
        div->shift = setup->bit_shift;
        div->latch = -EINVAL;
index 6c3329b..659dadb 100644 (file)
@@ -192,10 +192,9 @@ static void __init _register_dpll(void *user,
        dd->clk_bypass = __clk_get_hw(clk);
 
        /* register the clock */
-       clk = ti_clk_register(NULL, &clk_hw->hw, node->name);
+       clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, node->name);
 
        if (!IS_ERR(clk)) {
-               omap2_init_clk_hw_omap_clocks(&clk_hw->hw);
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
                kfree(clk_hw->hw.init->parent_names);
                kfree(clk_hw->hw.init);
@@ -265,14 +264,12 @@ static void _register_dpll_x2(struct device_node *node,
 #endif
 
        /* register the clock */
-       clk = ti_clk_register(NULL, &clk_hw->hw, name);
+       clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
 
-       if (IS_ERR(clk)) {
+       if (IS_ERR(clk))
                kfree(clk_hw);
-       } else {
-               omap2_init_clk_hw_omap_clocks(&clk_hw->hw);
+       else
                of_clk_add_provider(node, of_clk_src_simple_get, clk);
-       }
 }
 #endif
 
index 44b6b64..3dde6c8 100644 (file)
@@ -731,7 +731,7 @@ static struct clk_hw_omap *omap3_find_clkoutx2_dpll(struct clk_hw *hw)
        do {
                do {
                        hw = clk_hw_get_parent(hw);
-               } while (hw && (clk_hw_get_flags(hw) & CLK_IS_BASIC));
+               } while (hw && (!omap2_clk_is_hw_omap(hw)));
                if (!hw)
                        break;
                pclk = to_clk_hw_omap(hw);
index 1c78fff..504c0e9 100644 (file)
@@ -123,7 +123,7 @@ static struct clk *_register_gate(struct device *dev, const char *name,
 
        init.flags = flags;
 
-       clk = ti_clk_register(NULL, &clk_hw->hw, name);
+       clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
 
        if (IS_ERR(clk))
                kfree(clk_hw);
index 87e00c2..83e3442 100644 (file)
@@ -57,12 +57,10 @@ static struct clk *_register_interface(struct device *dev, const char *name,
        init.num_parents = 1;
        init.parent_names = &parent_name;
 
-       clk = ti_clk_register(NULL, &clk_hw->hw, name);
+       clk = ti_clk_register_omap_hw(NULL, &clk_hw->hw, name);
 
        if (IS_ERR(clk))
                kfree(clk_hw);
-       else
-               omap2_init_clk_hw_omap_clocks(&clk_hw->hw);
 
        return clk;
 }
index 883bdde..b7f9a4f 100644 (file)
@@ -143,7 +143,7 @@ static struct clk *_register_mux(struct device *dev, const char *name,
 
        init.name = name;
        init.ops = &ti_clk_mux_ops;
-       init.flags = flags | CLK_IS_BASIC;
+       init.flags = flags;
        init.parent_names = parent_names;
        init.num_parents = num_parents;
 
index ec11f55..5d2d42b 100644 (file)
@@ -47,7 +47,7 @@ static int uniphier_clk_cpugear_set_parent(struct clk_hw *hw, u8 index)
                return ret;
 
        ret = regmap_write_bits(gear->regmap,
-                               gear->regbase + UNIPHIER_CLK_CPUGEAR_SET,
+                               gear->regbase + UNIPHIER_CLK_CPUGEAR_UPD,
                                UNIPHIER_CLK_CPUGEAR_UPD_BIT,
                                UNIPHIER_CLK_CPUGEAR_UPD_BIT);
        if (ret)
index 6b40eb8..68bd3ab 100644 (file)
@@ -13,7 +13,7 @@
 #include <linux/clk-provider.h>
 #include <linux/err.h>
 #include <linux/module.h>
-#include <linux/platform_data/clk-lpss.h>
+#include <linux/platform_data/x86/clk-lpss.h>
 #include <linux/platform_device.h>
 
 static int lpt_clk_probe(struct platform_device *pdev)
index 3a0996f..25d4b97 100644 (file)
@@ -52,7 +52,8 @@ static int st_clk_probe(struct platform_device *pdev)
                0, st_data->base + MISCCLKCNTL1, OSCCLKENB,
                CLK_GATE_SET_TO_DISABLE, NULL);
 
-       clk_hw_register_clkdev(hws[ST_CLK_GATE], "oscout1", NULL);
+       devm_clk_hw_register_clkdev(&pdev->dev, hws[ST_CLK_GATE], "oscout1",
+                                   NULL);
 
        return 0;
 }
index f65cc0f..b0908ec 100644 (file)
@@ -669,8 +669,8 @@ static int zynqmp_clk_setup(struct device_node *np)
        if (ret)
                return ret;
 
-       zynqmp_data = kzalloc(sizeof(*zynqmp_data) + sizeof(*zynqmp_data) *
-                                               clock_max_idx, GFP_KERNEL);
+       zynqmp_data = kzalloc(struct_size(zynqmp_data, hws, clock_max_idx),
+                             GFP_KERNEL);
        if (!zynqmp_data)
                return -ENOMEM;
 
index 5951240..c364027 100644 (file)
@@ -154,6 +154,10 @@ static int omap_dm_timer_of_set_source(struct omap_dm_timer *timer)
        if (IS_ERR(parent))
                return -ENODEV;
 
+       /* Bail out if both clocks point to fck */
+       if (clk_is_match(parent, timer->fclk))
+               return 0;
+
        ret = clk_set_parent(timer->fclk, parent);
        if (ret < 0)
                pr_err("%s: failed to set parent\n", __func__);
@@ -864,7 +868,6 @@ static int omap_dm_timer_probe(struct platform_device *pdev)
        timer->pdev = pdev;
 
        pm_runtime_enable(dev);
-       pm_runtime_irq_safe(dev);
 
        if (!timer->reserved) {
                ret = pm_runtime_get_sync(dev);
index 6f23ebb..e35a886 100644 (file)
@@ -1530,17 +1530,16 @@ static unsigned int __cpufreq_get(struct cpufreq_policy *policy)
 {
        unsigned int ret_freq = 0;
 
-       if (!cpufreq_driver->get)
+       if (unlikely(policy_is_inactive(policy)) || !cpufreq_driver->get)
                return ret_freq;
 
        ret_freq = cpufreq_driver->get(policy->cpu);
 
        /*
-        * Updating inactive policies is invalid, so avoid doing that.  Also
-        * if fast frequency switching is used with the given policy, the check
+        * If fast frequency switching is used with the given policy, the check
         * against policy->cur is pointless, so skip it in that case too.
         */
-       if (unlikely(policy_is_inactive(policy)) || policy->fast_switch_enabled)
+       if (policy->fast_switch_enabled)
                return ret_freq;
 
        if (ret_freq && policy->cur &&
@@ -1569,10 +1568,7 @@ unsigned int cpufreq_get(unsigned int cpu)
 
        if (policy) {
                down_read(&policy->rwsem);
-
-               if (!policy_is_inactive(policy))
-                       ret_freq = __cpufreq_get(policy);
-
+               ret_freq = __cpufreq_get(policy);
                up_read(&policy->rwsem);
 
                cpufreq_cpu_put(policy);
index 50b1551..9ed46d1 100644 (file)
@@ -52,9 +52,9 @@ scmi_cpufreq_set_target(struct cpufreq_policy *policy, unsigned int index)
        int ret;
        struct scmi_data *priv = policy->driver_data;
        struct scmi_perf_ops *perf_ops = handle->perf_ops;
-       u64 freq = policy->freq_table[index].frequency * 1000;
+       u64 freq = policy->freq_table[index].frequency;
 
-       ret = perf_ops->freq_set(handle, priv->domain_id, freq, false);
+       ret = perf_ops->freq_set(handle, priv->domain_id, freq * 1000, false);
        if (!ret)
                arch_set_freq_scale(policy->related_cpus, freq,
                                    policy->cpuinfo.max_freq);
@@ -176,7 +176,7 @@ static int scmi_cpufreq_init(struct cpufreq_policy *policy)
 out_free_priv:
        kfree(priv);
 out_free_opp:
-       dev_pm_opp_cpumask_remove_table(policy->cpus);
+       dev_pm_opp_remove_all_dynamic(cpu_dev);
 
        return ret;
 }
@@ -187,8 +187,8 @@ static int scmi_cpufreq_exit(struct cpufreq_policy *policy)
 
        cpufreq_cooling_unregister(priv->cdev);
        dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
+       dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
        kfree(priv);
-       dev_pm_opp_cpumask_remove_table(policy->related_cpus);
 
        return 0;
 }
index 87a98ec..9944973 100644 (file)
@@ -177,7 +177,7 @@ out_free_cpufreq_table:
 out_free_priv:
        kfree(priv);
 out_free_opp:
-       dev_pm_opp_cpumask_remove_table(policy->cpus);
+       dev_pm_opp_remove_all_dynamic(cpu_dev);
 
        return ret;
 }
@@ -190,7 +190,7 @@ static int scpi_cpufreq_exit(struct cpufreq_policy *policy)
        clk_put(priv->clk);
        dev_pm_opp_free_cpufreq_table(priv->cpu_dev, &policy->freq_table);
        kfree(priv);
-       dev_pm_opp_cpumask_remove_table(policy->related_cpus);
+       dev_pm_opp_remove_all_dynamic(priv->cpu_dev);
 
        return 0;
 }
index b17d153..23a1b27 100644 (file)
@@ -21,7 +21,7 @@ static int __cpuidle poll_idle(struct cpuidle_device *dev,
        local_irq_enable();
        if (!current_set_polling_and_test()) {
                unsigned int loop_count = 0;
-               u64 limit = TICK_USEC;
+               u64 limit = TICK_NSEC;
                int i;
 
                for (i = 1; i < drv->state_count; i++) {
index 5a90075..0be55fc 100644 (file)
@@ -692,6 +692,7 @@ config CRYPTO_DEV_BCM_SPU
        depends on ARCH_BCM_IPROC
        depends on MAILBOX
        default m
+       select CRYPTO_AUTHENC
        select CRYPTO_DES
        select CRYPTO_MD5
        select CRYPTO_SHA1
index 63cb695..acf7988 100644 (file)
@@ -283,9 +283,9 @@ static u32 crypto4xx_put_pd_to_pdr(struct crypto4xx_device *dev, u32 idx)
  */
 static u32 crypto4xx_build_gdr(struct crypto4xx_device *dev)
 {
-       dev->gdr = dma_zalloc_coherent(dev->core_dev->device,
-                                      sizeof(struct ce_gd) * PPC4XX_NUM_GD,
-                                      &dev->gdr_pa, GFP_ATOMIC);
+       dev->gdr = dma_alloc_coherent(dev->core_dev->device,
+                                     sizeof(struct ce_gd) * PPC4XX_NUM_GD,
+                                     &dev->gdr_pa, GFP_ATOMIC);
        if (!dev->gdr)
                return -ENOMEM;
 
index c9393ff..5567cbd 100644 (file)
@@ -2845,44 +2845,28 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
        struct spu_hw *spu = &iproc_priv.spu;
        struct iproc_ctx_s *ctx = crypto_aead_ctx(cipher);
        struct crypto_tfm *tfm = crypto_aead_tfm(cipher);
-       struct rtattr *rta = (void *)key;
-       struct crypto_authenc_key_param *param;
-       const u8 *origkey = key;
-       const unsigned int origkeylen = keylen;
-
-       int ret = 0;
+       struct crypto_authenc_keys keys;
+       int ret;
 
        flow_log("%s() aead:%p key:%p keylen:%u\n", __func__, cipher, key,
                 keylen);
        flow_dump("  key: ", key, keylen);
 
-       if (!RTA_OK(rta, keylen))
-               goto badkey;
-       if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
-               goto badkey;
-       if (RTA_PAYLOAD(rta) < sizeof(*param))
+       ret = crypto_authenc_extractkeys(&keys, key, keylen);
+       if (ret)
                goto badkey;
 
-       param = RTA_DATA(rta);
-       ctx->enckeylen = be32_to_cpu(param->enckeylen);
-
-       key += RTA_ALIGN(rta->rta_len);
-       keylen -= RTA_ALIGN(rta->rta_len);
-
-       if (keylen < ctx->enckeylen)
-               goto badkey;
-       if (ctx->enckeylen > MAX_KEY_SIZE)
+       if (keys.enckeylen > MAX_KEY_SIZE ||
+           keys.authkeylen > MAX_KEY_SIZE)
                goto badkey;
 
-       ctx->authkeylen = keylen - ctx->enckeylen;
-
-       if (ctx->authkeylen > MAX_KEY_SIZE)
-               goto badkey;
+       ctx->enckeylen = keys.enckeylen;
+       ctx->authkeylen = keys.authkeylen;
 
-       memcpy(ctx->enckey, key + ctx->authkeylen, ctx->enckeylen);
+       memcpy(ctx->enckey, keys.enckey, keys.enckeylen);
        /* May end up padding auth key. So make sure it's zeroed. */
        memset(ctx->authkey, 0, sizeof(ctx->authkey));
-       memcpy(ctx->authkey, key, ctx->authkeylen);
+       memcpy(ctx->authkey, keys.authkey, keys.authkeylen);
 
        switch (ctx->alg->cipher_info.alg) {
        case CIPHER_ALG_DES:
@@ -2890,7 +2874,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
                        u32 tmp[DES_EXPKEY_WORDS];
                        u32 flags = CRYPTO_TFM_RES_WEAK_KEY;
 
-                       if (des_ekey(tmp, key) == 0) {
+                       if (des_ekey(tmp, keys.enckey) == 0) {
                                if (crypto_aead_get_flags(cipher) &
                                    CRYPTO_TFM_REQ_WEAK_KEY) {
                                        crypto_aead_set_flags(cipher, flags);
@@ -2905,7 +2889,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
                break;
        case CIPHER_ALG_3DES:
                if (ctx->enckeylen == (DES_KEY_SIZE * 3)) {
-                       const u32 *K = (const u32 *)key;
+                       const u32 *K = (const u32 *)keys.enckey;
                        u32 flags = CRYPTO_TFM_RES_BAD_KEY_SCHED;
 
                        if (!((K[0] ^ K[2]) | (K[1] ^ K[3])) ||
@@ -2956,9 +2940,7 @@ static int aead_authenc_setkey(struct crypto_aead *cipher,
                ctx->fallback_cipher->base.crt_flags &= ~CRYPTO_TFM_REQ_MASK;
                ctx->fallback_cipher->base.crt_flags |=
                    tfm->crt_flags & CRYPTO_TFM_REQ_MASK;
-               ret =
-                   crypto_aead_setkey(ctx->fallback_cipher, origkey,
-                                      origkeylen);
+               ret = crypto_aead_setkey(ctx->fallback_cipher, key, keylen);
                if (ret) {
                        flow_log("  fallback setkey() returned:%d\n", ret);
                        tfm->crt_flags &= ~CRYPTO_TFM_RES_MASK;
index 92e593e..80ae69f 100644 (file)
@@ -3476,7 +3476,7 @@ static int __init caam_algapi_init(void)
                 * Skip algorithms requiring message digests
                 * if MD or MD size is not supported by device.
                 */
-               if ((c2_alg_sel & ~OP_ALG_ALGSEL_SUBMASK) == 0x40 &&
+               if (is_mdha(c2_alg_sel) &&
                    (!md_inst || t_alg->aead.maxauthsize > md_limit))
                        continue;
 
index 81712aa..bb1a2cd 100644 (file)
@@ -1072,13 +1072,16 @@ static int ahash_final_no_ctx(struct ahash_request *req)
 
        desc = edesc->hw_desc;
 
-       state->buf_dma = dma_map_single(jrdev, buf, buflen, DMA_TO_DEVICE);
-       if (dma_mapping_error(jrdev, state->buf_dma)) {
-               dev_err(jrdev, "unable to map src\n");
-               goto unmap;
-       }
+       if (buflen) {
+               state->buf_dma = dma_map_single(jrdev, buf, buflen,
+                                               DMA_TO_DEVICE);
+               if (dma_mapping_error(jrdev, state->buf_dma)) {
+                       dev_err(jrdev, "unable to map src\n");
+                       goto unmap;
+               }
 
-       append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
+               append_seq_in_ptr(desc, state->buf_dma, buflen, 0);
+       }
 
        edesc->dst_dma = map_seq_out_ptr_result(desc, jrdev, req->result,
                                                digestsize);
index ec10230..4b6854b 100644 (file)
 #define OP_ALG_ALGSEL_DES      (0x20 << OP_ALG_ALGSEL_SHIFT)
 #define OP_ALG_ALGSEL_3DES     (0x21 << OP_ALG_ALGSEL_SHIFT)
 #define OP_ALG_ALGSEL_ARC4     (0x30 << OP_ALG_ALGSEL_SHIFT)
+#define OP_ALG_CHA_MDHA                (0x40 << OP_ALG_ALGSEL_SHIFT)
 #define OP_ALG_ALGSEL_MD5      (0x40 << OP_ALG_ALGSEL_SHIFT)
 #define OP_ALG_ALGSEL_SHA1     (0x41 << OP_ALG_ALGSEL_SHIFT)
 #define OP_ALG_ALGSEL_SHA224   (0x42 << OP_ALG_ALGSEL_SHIFT)
index 67ea940..8c6b83e 100644 (file)
@@ -7,6 +7,9 @@
 
 #ifndef CAAM_ERROR_H
 #define CAAM_ERROR_H
+
+#include "desc.h"
+
 #define CAAM_ERROR_STR_MAX 302
 
 void caam_strstatus(struct device *dev, u32 status, bool qi_v2);
@@ -17,4 +20,10 @@ void caam_strstatus(struct device *dev, u32 status, bool qi_v2);
 void caam_dump_sg(const char *level, const char *prefix_str, int prefix_type,
                  int rowsize, int groupsize, struct scatterlist *sg,
                  size_t tlen, bool ascii);
+
+static inline bool is_mdha(u32 algtype)
+{
+       return (algtype & OP_ALG_ALGSEL_MASK & ~OP_ALG_ALGSEL_SUBMASK) ==
+              OP_ALG_CHA_MDHA;
+}
 #endif /* CAAM_ERROR_H */
index 06ad85a..a876535 100644 (file)
@@ -278,8 +278,8 @@ static int cpt_ucode_load_fw(struct cpt_device *cpt, const u8 *fw, bool is_ae)
        mcode->num_cores = is_ae ? 6 : 10;
 
        /*  Allocate DMAable space */
-       mcode->code = dma_zalloc_coherent(&cpt->pdev->dev, mcode->code_size,
-                                         &mcode->phys_base, GFP_KERNEL);
+       mcode->code = dma_alloc_coherent(&cpt->pdev->dev, mcode->code_size,
+                                        &mcode->phys_base, GFP_KERNEL);
        if (!mcode->code) {
                dev_err(dev, "Unable to allocate space for microcode");
                ret = -ENOMEM;
index 5c796ed..2ca431e 100644 (file)
@@ -236,9 +236,10 @@ static int alloc_command_queues(struct cpt_vf *cptvf,
 
                        c_size = (rem_q_size > qcsize_bytes) ? qcsize_bytes :
                                        rem_q_size;
-                       curr->head = (u8 *)dma_zalloc_coherent(&pdev->dev,
-                                         c_size + CPT_NEXT_CHUNK_PTR_SIZE,
-                                         &curr->dma_addr, GFP_KERNEL);
+                       curr->head = (u8 *)dma_alloc_coherent(&pdev->dev,
+                                                             c_size + CPT_NEXT_CHUNK_PTR_SIZE,
+                                                             &curr->dma_addr,
+                                                             GFP_KERNEL);
                        if (!curr->head) {
                                dev_err(&pdev->dev, "Command Q (%d) chunk (%d) allocation failed\n",
                                        i, queue->nchunks);
index 9138bae..4ace9bc 100644 (file)
@@ -25,9 +25,9 @@ static int nitrox_cmdq_init(struct nitrox_cmdq *cmdq, int align_bytes)
        struct nitrox_device *ndev = cmdq->ndev;
 
        cmdq->qsize = (ndev->qlen * cmdq->instr_size) + align_bytes;
-       cmdq->unalign_base = dma_zalloc_coherent(DEV(ndev), cmdq->qsize,
-                                                &cmdq->unalign_dma,
-                                                GFP_KERNEL);
+       cmdq->unalign_base = dma_alloc_coherent(DEV(ndev), cmdq->qsize,
+                                               &cmdq->unalign_dma,
+                                               GFP_KERNEL);
        if (!cmdq->unalign_base)
                return -ENOMEM;
 
index e34e4df..4c97478 100644 (file)
@@ -537,6 +537,8 @@ static void process_response_list(struct nitrox_cmdq *cmdq)
        struct nitrox_device *ndev = cmdq->ndev;
        struct nitrox_softreq *sr;
        int req_completed = 0, err = 0, budget;
+       completion_t callback;
+       void *cb_arg;
 
        /* check all pending requests */
        budget = atomic_read(&cmdq->pending_count);
@@ -564,13 +566,13 @@ static void process_response_list(struct nitrox_cmdq *cmdq)
                smp_mb__after_atomic();
                /* remove from response list */
                response_list_del(sr, cmdq);
-
                /* ORH error code */
                err = READ_ONCE(*sr->resp.orh) & 0xff;
+               callback = sr->callback;
+               cb_arg = sr->cb_arg;
                softreq_destroy(sr);
-
-               if (sr->callback)
-                       sr->callback(sr->cb_arg, err);
+               if (callback)
+                       callback(cb_arg, err);
 
                req_completed++;
        }
index 44a4d27..c9bfd4f 100644 (file)
@@ -822,9 +822,9 @@ static int ccp5_init(struct ccp_device *ccp)
                /* Page alignment satisfies our needs for N <= 128 */
                BUILD_BUG_ON(COMMANDS_PER_QUEUE > 128);
                cmd_q->qsize = Q_SIZE(Q_DESC_SIZE);
-               cmd_q->qbase = dma_zalloc_coherent(dev, cmd_q->qsize,
-                                                  &cmd_q->qbase_dma,
-                                                  GFP_KERNEL);
+               cmd_q->qbase = dma_alloc_coherent(dev, cmd_q->qsize,
+                                                 &cmd_q->qbase_dma,
+                                                 GFP_KERNEL);
                if (!cmd_q->qbase) {
                        dev_err(dev, "unable to allocate command queue\n");
                        ret = -ENOMEM;
index f2643cd..a3527c0 100644 (file)
@@ -549,13 +549,12 @@ static int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
                          unsigned int keylen)
 {
        struct cc_aead_ctx *ctx = crypto_aead_ctx(tfm);
-       struct rtattr *rta = (struct rtattr *)key;
        struct cc_crypto_req cc_req = {};
-       struct crypto_authenc_key_param *param;
        struct cc_hw_desc desc[MAX_AEAD_SETKEY_SEQ];
-       int rc = -EINVAL;
        unsigned int seq_len = 0;
        struct device *dev = drvdata_to_dev(ctx->drvdata);
+       const u8 *enckey, *authkey;
+       int rc;
 
        dev_dbg(dev, "Setting key in context @%p for %s. key=%p keylen=%u\n",
                ctx, crypto_tfm_alg_name(crypto_aead_tfm(tfm)), key, keylen);
@@ -563,35 +562,33 @@ static int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
        /* STAT_PHASE_0: Init and sanity checks */
 
        if (ctx->auth_mode != DRV_HASH_NULL) { /* authenc() alg. */
-               if (!RTA_OK(rta, keylen))
-                       goto badkey;
-               if (rta->rta_type != CRYPTO_AUTHENC_KEYA_PARAM)
-                       goto badkey;
-               if (RTA_PAYLOAD(rta) < sizeof(*param))
-                       goto badkey;
-               param = RTA_DATA(rta);
-               ctx->enc_keylen = be32_to_cpu(param->enckeylen);
-               key += RTA_ALIGN(rta->rta_len);
-               keylen -= RTA_ALIGN(rta->rta_len);
-               if (keylen < ctx->enc_keylen)
+               struct crypto_authenc_keys keys;
+
+               rc = crypto_authenc_extractkeys(&keys, key, keylen);
+               if (rc)
                        goto badkey;
-               ctx->auth_keylen = keylen - ctx->enc_keylen;
+               enckey = keys.enckey;
+               authkey = keys.authkey;
+               ctx->enc_keylen = keys.enckeylen;
+               ctx->auth_keylen = keys.authkeylen;
 
                if (ctx->cipher_mode == DRV_CIPHER_CTR) {
                        /* the nonce is stored in bytes at end of key */
+                       rc = -EINVAL;
                        if (ctx->enc_keylen <
                            (AES_MIN_KEY_SIZE + CTR_RFC3686_NONCE_SIZE))
                                goto badkey;
                        /* Copy nonce from last 4 bytes in CTR key to
                         *  first 4 bytes in CTR IV
                         */
-                       memcpy(ctx->ctr_nonce, key + ctx->auth_keylen +
-                              ctx->enc_keylen - CTR_RFC3686_NONCE_SIZE,
-                              CTR_RFC3686_NONCE_SIZE);
+                       memcpy(ctx->ctr_nonce, enckey + ctx->enc_keylen -
+                              CTR_RFC3686_NONCE_SIZE, CTR_RFC3686_NONCE_SIZE);
                        /* Set CTR key size */
                        ctx->enc_keylen -= CTR_RFC3686_NONCE_SIZE;
                }
        } else { /* non-authenc - has just one key */
+               enckey = key;
+               authkey = NULL;
                ctx->enc_keylen = keylen;
                ctx->auth_keylen = 0;
        }
@@ -603,13 +600,14 @@ static int cc_aead_setkey(struct crypto_aead *tfm, const u8 *key,
        /* STAT_PHASE_1: Copy key to ctx */
 
        /* Get key material */
-       memcpy(ctx->enckey, key + ctx->auth_keylen, ctx->enc_keylen);
+       memcpy(ctx->enckey, enckey, ctx->enc_keylen);
        if (ctx->enc_keylen == 24)
                memset(ctx->enckey + 24, 0, CC_AES_KEY_SIZE_MAX - 24);
        if (ctx->auth_mode == DRV_HASH_XCBC_MAC) {
-               memcpy(ctx->auth_state.xcbc.xcbc_keys, key, ctx->auth_keylen);
+               memcpy(ctx->auth_state.xcbc.xcbc_keys, authkey,
+                      ctx->auth_keylen);
        } else if (ctx->auth_mode != DRV_HASH_NULL) { /* HMAC */
-               rc = cc_get_plain_hmac_key(tfm, key, ctx->auth_keylen);
+               rc = cc_get_plain_hmac_key(tfm, authkey, ctx->auth_keylen);
                if (rc)
                        goto badkey;
        }
index 8ada308..b0125ad 100644 (file)
@@ -380,7 +380,7 @@ static int init_cc_resources(struct platform_device *plat_dev)
        rc = cc_ivgen_init(new_drvdata);
        if (rc) {
                dev_err(dev, "cc_ivgen_init failed\n");
-               goto post_power_mgr_err;
+               goto post_buf_mgr_err;
        }
 
        /* Allocate crypto algs */
@@ -403,6 +403,9 @@ static int init_cc_resources(struct platform_device *plat_dev)
                goto post_hash_err;
        }
 
+       /* All set, we can allow autosuspend */
+       cc_pm_go(new_drvdata);
+
        /* If we got here and FIPS mode is enabled
         * it means all FIPS test passed, so let TEE
         * know we're good.
@@ -417,8 +420,6 @@ post_cipher_err:
        cc_cipher_free(new_drvdata);
 post_ivgen_err:
        cc_ivgen_fini(new_drvdata);
-post_power_mgr_err:
-       cc_pm_fini(new_drvdata);
 post_buf_mgr_err:
         cc_buffer_mgr_fini(new_drvdata);
 post_req_mgr_err:
index d990f47..6ff7e75 100644 (file)
@@ -100,20 +100,19 @@ int cc_pm_put_suspend(struct device *dev)
 
 int cc_pm_init(struct cc_drvdata *drvdata)
 {
-       int rc = 0;
        struct device *dev = drvdata_to_dev(drvdata);
 
        /* must be before the enabling to avoid resdundent suspending */
        pm_runtime_set_autosuspend_delay(dev, CC_SUSPEND_TIMEOUT);
        pm_runtime_use_autosuspend(dev);
        /* activate the PM module */
-       rc = pm_runtime_set_active(dev);
-       if (rc)
-               return rc;
-       /* enable the PM module*/
-       pm_runtime_enable(dev);
+       return pm_runtime_set_active(dev);
+}
 
-       return rc;
+/* enable the PM module*/
+void cc_pm_go(struct cc_drvdata *drvdata)
+{
+       pm_runtime_enable(drvdata_to_dev(drvdata));
 }
 
 void cc_pm_fini(struct cc_drvdata *drvdata)
index 020a540..f626243 100644 (file)
@@ -16,6 +16,7 @@
 extern const struct dev_pm_ops ccree_pm;
 
 int cc_pm_init(struct cc_drvdata *drvdata);
+void cc_pm_go(struct cc_drvdata *drvdata);
 void cc_pm_fini(struct cc_drvdata *drvdata);
 int cc_pm_suspend(struct device *dev);
 int cc_pm_resume(struct device *dev);
@@ -29,6 +30,8 @@ static inline int cc_pm_init(struct cc_drvdata *drvdata)
        return 0;
 }
 
+static void cc_pm_go(struct cc_drvdata *drvdata) {}
+
 static inline void cc_pm_fini(struct cc_drvdata *drvdata) {}
 
 static inline int cc_pm_suspend(struct device *dev)
index cdc4f9a..adc0cd8 100644 (file)
@@ -241,8 +241,8 @@ static int sec_alg_skcipher_setkey(struct crypto_skcipher *tfm,
                memset(ctx->key, 0, SEC_MAX_CIPHER_KEY);
        } else {
                /* new key */
-               ctx->key = dma_zalloc_coherent(dev, SEC_MAX_CIPHER_KEY,
-                                              &ctx->pkey, GFP_KERNEL);
+               ctx->key = dma_alloc_coherent(dev, SEC_MAX_CIPHER_KEY,
+                                             &ctx->pkey, GFP_KERNEL);
                if (!ctx->key) {
                        mutex_unlock(&ctx->lock);
                        return -ENOMEM;
index c1ee4e7..91ee2bb 100644 (file)
@@ -1082,9 +1082,8 @@ static int sec_queue_res_cfg(struct sec_queue *queue)
        struct sec_queue_ring_db *ring_db = &queue->ring_db;
        int ret;
 
-       ring_cmd->vaddr = dma_zalloc_coherent(dev, SEC_Q_CMD_SIZE,
-                                             &ring_cmd->paddr,
-                                             GFP_KERNEL);
+       ring_cmd->vaddr = dma_alloc_coherent(dev, SEC_Q_CMD_SIZE,
+                                            &ring_cmd->paddr, GFP_KERNEL);
        if (!ring_cmd->vaddr)
                return -ENOMEM;
 
@@ -1092,17 +1091,15 @@ static int sec_queue_res_cfg(struct sec_queue *queue)
        mutex_init(&ring_cmd->lock);
        ring_cmd->callback = sec_alg_callback;
 
-       ring_cq->vaddr = dma_zalloc_coherent(dev, SEC_Q_CQ_SIZE,
-                                            &ring_cq->paddr,
-                                            GFP_KERNEL);
+       ring_cq->vaddr = dma_alloc_coherent(dev, SEC_Q_CQ_SIZE,
+                                           &ring_cq->paddr, GFP_KERNEL);
        if (!ring_cq->vaddr) {
                ret = -ENOMEM;
                goto err_free_ring_cmd;
        }
 
-       ring_db->vaddr = dma_zalloc_coherent(dev, SEC_Q_DB_SIZE,
-                                            &ring_db->paddr,
-                                            GFP_KERNEL);
+       ring_db->vaddr = dma_alloc_coherent(dev, SEC_Q_DB_SIZE,
+                                           &ring_db->paddr, GFP_KERNEL);
        if (!ring_db->vaddr) {
                ret = -ENOMEM;
                goto err_free_ring_cq;
index 19fba99..1b0d156 100644 (file)
@@ -260,9 +260,9 @@ static int setup_crypt_desc(void)
 {
        struct device *dev = &pdev->dev;
        BUILD_BUG_ON(sizeof(struct crypt_ctl) != 64);
-       crypt_virt = dma_zalloc_coherent(dev,
-                                        NPE_QLEN * sizeof(struct crypt_ctl),
-                                        &crypt_phys, GFP_ATOMIC);
+       crypt_virt = dma_alloc_coherent(dev,
+                                       NPE_QLEN * sizeof(struct crypt_ctl),
+                                       &crypt_phys, GFP_ATOMIC);
        if (!crypt_virt)
                return -ENOMEM;
        return 0;
index ee0404e..5660e5e 100644 (file)
@@ -453,17 +453,17 @@ static int mtk_desc_ring_alloc(struct mtk_cryp *cryp)
                if (!ring[i])
                        goto err_cleanup;
 
-               ring[i]->cmd_base = dma_zalloc_coherent(cryp->dev,
-                                          MTK_DESC_RING_SZ,
-                                          &ring[i]->cmd_dma,
-                                          GFP_KERNEL);
+               ring[i]->cmd_base = dma_alloc_coherent(cryp->dev,
+                                                      MTK_DESC_RING_SZ,
+                                                      &ring[i]->cmd_dma,
+                                                      GFP_KERNEL);
                if (!ring[i]->cmd_base)
                        goto err_cleanup;
 
-               ring[i]->res_base = dma_zalloc_coherent(cryp->dev,
-                                          MTK_DESC_RING_SZ,
-                                          &ring[i]->res_dma,
-                                          GFP_KERNEL);
+               ring[i]->res_base = dma_alloc_coherent(cryp->dev,
+                                                      MTK_DESC_RING_SZ,
+                                                      &ring[i]->res_dma,
+                                                      GFP_KERNEL);
                if (!ring[i]->res_base)
                        goto err_cleanup;
 
index 3744b22..d28cba3 100644 (file)
@@ -244,18 +244,18 @@ int adf_init_admin_comms(struct adf_accel_dev *accel_dev)
                             dev_to_node(&GET_DEV(accel_dev)));
        if (!admin)
                return -ENOMEM;
-       admin->virt_addr = dma_zalloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
-                                              &admin->phy_addr, GFP_KERNEL);
+       admin->virt_addr = dma_alloc_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
+                                             &admin->phy_addr, GFP_KERNEL);
        if (!admin->virt_addr) {
                dev_err(&GET_DEV(accel_dev), "Failed to allocate dma buff\n");
                kfree(admin);
                return -ENOMEM;
        }
 
-       admin->virt_tbl_addr = dma_zalloc_coherent(&GET_DEV(accel_dev),
-                                                  PAGE_SIZE,
-                                                  &admin->const_tbl_addr,
-                                                  GFP_KERNEL);
+       admin->virt_tbl_addr = dma_alloc_coherent(&GET_DEV(accel_dev),
+                                                 PAGE_SIZE,
+                                                 &admin->const_tbl_addr,
+                                                 GFP_KERNEL);
        if (!admin->virt_tbl_addr) {
                dev_err(&GET_DEV(accel_dev), "Failed to allocate const_tbl\n");
                dma_free_coherent(&GET_DEV(accel_dev), PAGE_SIZE,
index d269829..975c751 100644 (file)
@@ -601,15 +601,15 @@ static int qat_alg_aead_setkey(struct crypto_aead *tfm, const uint8_t *key,
 
                dev = &GET_DEV(inst->accel_dev);
                ctx->inst = inst;
-               ctx->enc_cd = dma_zalloc_coherent(dev, sizeof(*ctx->enc_cd),
-                                                 &ctx->enc_cd_paddr,
-                                                 GFP_ATOMIC);
+               ctx->enc_cd = dma_alloc_coherent(dev, sizeof(*ctx->enc_cd),
+                                                &ctx->enc_cd_paddr,
+                                                GFP_ATOMIC);
                if (!ctx->enc_cd) {
                        return -ENOMEM;
                }
-               ctx->dec_cd = dma_zalloc_coherent(dev, sizeof(*ctx->dec_cd),
-                                                 &ctx->dec_cd_paddr,
-                                                 GFP_ATOMIC);
+               ctx->dec_cd = dma_alloc_coherent(dev, sizeof(*ctx->dec_cd),
+                                                &ctx->dec_cd_paddr,
+                                                GFP_ATOMIC);
                if (!ctx->dec_cd) {
                        goto out_free_enc;
                }
@@ -933,16 +933,16 @@ static int qat_alg_ablkcipher_setkey(struct crypto_ablkcipher *tfm,
 
                dev = &GET_DEV(inst->accel_dev);
                ctx->inst = inst;
-               ctx->enc_cd = dma_zalloc_coherent(dev, sizeof(*ctx->enc_cd),
-                                                 &ctx->enc_cd_paddr,
-                                                 GFP_ATOMIC);
+               ctx->enc_cd = dma_alloc_coherent(dev, sizeof(*ctx->enc_cd),
+                                                &ctx->enc_cd_paddr,
+                                                GFP_ATOMIC);
                if (!ctx->enc_cd) {
                        spin_unlock(&ctx->lock);
                        return -ENOMEM;
                }
-               ctx->dec_cd = dma_zalloc_coherent(dev, sizeof(*ctx->dec_cd),
-                                                 &ctx->dec_cd_paddr,
-                                                 GFP_ATOMIC);
+               ctx->dec_cd = dma_alloc_coherent(dev, sizeof(*ctx->dec_cd),
+                                                &ctx->dec_cd_paddr,
+                                                GFP_ATOMIC);
                if (!ctx->dec_cd) {
                        spin_unlock(&ctx->lock);
                        goto out_free_enc;
index 320e785..c9f3247 100644 (file)
@@ -332,10 +332,10 @@ static int qat_dh_compute_value(struct kpp_request *req)
                } else {
                        int shift = ctx->p_size - req->src_len;
 
-                       qat_req->src_align = dma_zalloc_coherent(dev,
-                                                                ctx->p_size,
-                                                                &qat_req->in.dh.in.b,
-                                                                GFP_KERNEL);
+                       qat_req->src_align = dma_alloc_coherent(dev,
+                                                               ctx->p_size,
+                                                               &qat_req->in.dh.in.b,
+                                                               GFP_KERNEL);
                        if (unlikely(!qat_req->src_align))
                                return ret;
 
@@ -360,9 +360,9 @@ static int qat_dh_compute_value(struct kpp_request *req)
                        goto unmap_src;
 
        } else {
-               qat_req->dst_align = dma_zalloc_coherent(dev, ctx->p_size,
-                                                        &qat_req->out.dh.r,
-                                                        GFP_KERNEL);
+               qat_req->dst_align = dma_alloc_coherent(dev, ctx->p_size,
+                                                       &qat_req->out.dh.r,
+                                                       GFP_KERNEL);
                if (unlikely(!qat_req->dst_align))
                        goto unmap_src;
        }
@@ -447,7 +447,7 @@ static int qat_dh_set_params(struct qat_dh_ctx *ctx, struct dh *params)
                return -EINVAL;
 
        ctx->p_size = params->p_size;
-       ctx->p = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_p, GFP_KERNEL);
+       ctx->p = dma_alloc_coherent(dev, ctx->p_size, &ctx->dma_p, GFP_KERNEL);
        if (!ctx->p)
                return -ENOMEM;
        memcpy(ctx->p, params->p, ctx->p_size);
@@ -458,7 +458,7 @@ static int qat_dh_set_params(struct qat_dh_ctx *ctx, struct dh *params)
                return 0;
        }
 
-       ctx->g = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_g, GFP_KERNEL);
+       ctx->g = dma_alloc_coherent(dev, ctx->p_size, &ctx->dma_g, GFP_KERNEL);
        if (!ctx->g)
                return -ENOMEM;
        memcpy(ctx->g + (ctx->p_size - params->g_size), params->g,
@@ -503,8 +503,8 @@ static int qat_dh_set_secret(struct crypto_kpp *tfm, const void *buf,
        if (ret < 0)
                goto err_clear_ctx;
 
-       ctx->xa = dma_zalloc_coherent(dev, ctx->p_size, &ctx->dma_xa,
-                                     GFP_KERNEL);
+       ctx->xa = dma_alloc_coherent(dev, ctx->p_size, &ctx->dma_xa,
+                                    GFP_KERNEL);
        if (!ctx->xa) {
                ret = -ENOMEM;
                goto err_clear_ctx;
@@ -737,9 +737,9 @@ static int qat_rsa_enc(struct akcipher_request *req)
        } else {
                int shift = ctx->key_sz - req->src_len;
 
-               qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz,
-                                                        &qat_req->in.rsa.enc.m,
-                                                        GFP_KERNEL);
+               qat_req->src_align = dma_alloc_coherent(dev, ctx->key_sz,
+                                                       &qat_req->in.rsa.enc.m,
+                                                       GFP_KERNEL);
                if (unlikely(!qat_req->src_align))
                        return ret;
 
@@ -756,9 +756,9 @@ static int qat_rsa_enc(struct akcipher_request *req)
                        goto unmap_src;
 
        } else {
-               qat_req->dst_align = dma_zalloc_coherent(dev, ctx->key_sz,
-                                                        &qat_req->out.rsa.enc.c,
-                                                        GFP_KERNEL);
+               qat_req->dst_align = dma_alloc_coherent(dev, ctx->key_sz,
+                                                       &qat_req->out.rsa.enc.c,
+                                                       GFP_KERNEL);
                if (unlikely(!qat_req->dst_align))
                        goto unmap_src;
 
@@ -881,9 +881,9 @@ static int qat_rsa_dec(struct akcipher_request *req)
        } else {
                int shift = ctx->key_sz - req->src_len;
 
-               qat_req->src_align = dma_zalloc_coherent(dev, ctx->key_sz,
-                                                        &qat_req->in.rsa.dec.c,
-                                                        GFP_KERNEL);
+               qat_req->src_align = dma_alloc_coherent(dev, ctx->key_sz,
+                                                       &qat_req->in.rsa.dec.c,
+                                                       GFP_KERNEL);
                if (unlikely(!qat_req->src_align))
                        return ret;
 
@@ -900,9 +900,9 @@ static int qat_rsa_dec(struct akcipher_request *req)
                        goto unmap_src;
 
        } else {
-               qat_req->dst_align = dma_zalloc_coherent(dev, ctx->key_sz,
-                                                        &qat_req->out.rsa.dec.m,
-                                                        GFP_KERNEL);
+               qat_req->dst_align = dma_alloc_coherent(dev, ctx->key_sz,
+                                                       &qat_req->out.rsa.dec.m,
+                                                       GFP_KERNEL);
                if (unlikely(!qat_req->dst_align))
                        goto unmap_src;
 
@@ -989,7 +989,7 @@ static int qat_rsa_set_n(struct qat_rsa_ctx *ctx, const char *value,
                goto err;
 
        ret = -ENOMEM;
-       ctx->n = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_n, GFP_KERNEL);
+       ctx->n = dma_alloc_coherent(dev, ctx->key_sz, &ctx->dma_n, GFP_KERNEL);
        if (!ctx->n)
                goto err;
 
@@ -1018,7 +1018,7 @@ static int qat_rsa_set_e(struct qat_rsa_ctx *ctx, const char *value,
                return -EINVAL;
        }
 
-       ctx->e = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_e, GFP_KERNEL);
+       ctx->e = dma_alloc_coherent(dev, ctx->key_sz, &ctx->dma_e, GFP_KERNEL);
        if (!ctx->e)
                return -ENOMEM;
 
@@ -1044,7 +1044,7 @@ static int qat_rsa_set_d(struct qat_rsa_ctx *ctx, const char *value,
                goto err;
 
        ret = -ENOMEM;
-       ctx->d = dma_zalloc_coherent(dev, ctx->key_sz, &ctx->dma_d, GFP_KERNEL);
+       ctx->d = dma_alloc_coherent(dev, ctx->key_sz, &ctx->dma_d, GFP_KERNEL);
        if (!ctx->d)
                goto err;
 
@@ -1077,7 +1077,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
        qat_rsa_drop_leading_zeros(&ptr, &len);
        if (!len)
                goto err;
-       ctx->p = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_p, GFP_KERNEL);
+       ctx->p = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_p, GFP_KERNEL);
        if (!ctx->p)
                goto err;
        memcpy(ctx->p + (half_key_sz - len), ptr, len);
@@ -1088,7 +1088,7 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
        qat_rsa_drop_leading_zeros(&ptr, &len);
        if (!len)
                goto free_p;
-       ctx->q = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_q, GFP_KERNEL);
+       ctx->q = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_q, GFP_KERNEL);
        if (!ctx->q)
                goto free_p;
        memcpy(ctx->q + (half_key_sz - len), ptr, len);
@@ -1099,8 +1099,8 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
        qat_rsa_drop_leading_zeros(&ptr, &len);
        if (!len)
                goto free_q;
-       ctx->dp = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_dp,
-                                     GFP_KERNEL);
+       ctx->dp = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_dp,
+                                    GFP_KERNEL);
        if (!ctx->dp)
                goto free_q;
        memcpy(ctx->dp + (half_key_sz - len), ptr, len);
@@ -1111,8 +1111,8 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
        qat_rsa_drop_leading_zeros(&ptr, &len);
        if (!len)
                goto free_dp;
-       ctx->dq = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_dq,
-                                     GFP_KERNEL);
+       ctx->dq = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_dq,
+                                    GFP_KERNEL);
        if (!ctx->dq)
                goto free_dp;
        memcpy(ctx->dq + (half_key_sz - len), ptr, len);
@@ -1123,8 +1123,8 @@ static void qat_rsa_setkey_crt(struct qat_rsa_ctx *ctx, struct rsa_key *rsa_key)
        qat_rsa_drop_leading_zeros(&ptr, &len);
        if (!len)
                goto free_dq;
-       ctx->qinv = dma_zalloc_coherent(dev, half_key_sz, &ctx->dma_qinv,
-                                       GFP_KERNEL);
+       ctx->qinv = dma_alloc_coherent(dev, half_key_sz, &ctx->dma_qinv,
+                                      GFP_KERNEL);
        if (!ctx->qinv)
                goto free_dq;
        memcpy(ctx->qinv + (half_key_sz - len), ptr, len);
index 45e2070..f8e2c5c 100644 (file)
@@ -1361,23 +1361,18 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
        struct talitos_private *priv = dev_get_drvdata(dev);
        bool is_sec1 = has_ftr_sec1(priv);
        int max_len = is_sec1 ? TALITOS1_MAX_DATA_LEN : TALITOS2_MAX_DATA_LEN;
-       void *err;
 
        if (cryptlen + authsize > max_len) {
                dev_err(dev, "length exceeds h/w max limit\n");
                return ERR_PTR(-EINVAL);
        }
 
-       if (ivsize)
-               iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
-
        if (!dst || dst == src) {
                src_len = assoclen + cryptlen + authsize;
                src_nents = sg_nents_for_len(src, src_len);
                if (src_nents < 0) {
                        dev_err(dev, "Invalid number of src SG.\n");
-                       err = ERR_PTR(-EINVAL);
-                       goto error_sg;
+                       return ERR_PTR(-EINVAL);
                }
                src_nents = (src_nents == 1) ? 0 : src_nents;
                dst_nents = dst ? src_nents : 0;
@@ -1387,16 +1382,14 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                src_nents = sg_nents_for_len(src, src_len);
                if (src_nents < 0) {
                        dev_err(dev, "Invalid number of src SG.\n");
-                       err = ERR_PTR(-EINVAL);
-                       goto error_sg;
+                       return ERR_PTR(-EINVAL);
                }
                src_nents = (src_nents == 1) ? 0 : src_nents;
                dst_len = assoclen + cryptlen + (encrypt ? authsize : 0);
                dst_nents = sg_nents_for_len(dst, dst_len);
                if (dst_nents < 0) {
                        dev_err(dev, "Invalid number of dst SG.\n");
-                       err = ERR_PTR(-EINVAL);
-                       goto error_sg;
+                       return ERR_PTR(-EINVAL);
                }
                dst_nents = (dst_nents == 1) ? 0 : dst_nents;
        }
@@ -1423,11 +1416,14 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
        /* if its a ahash, add space for a second desc next to the first one */
        if (is_sec1 && !dst)
                alloc_len += sizeof(struct talitos_desc);
+       alloc_len += ivsize;
 
        edesc = kmalloc(alloc_len, GFP_DMA | flags);
-       if (!edesc) {
-               err = ERR_PTR(-ENOMEM);
-               goto error_sg;
+       if (!edesc)
+               return ERR_PTR(-ENOMEM);
+       if (ivsize) {
+               iv = memcpy(((u8 *)edesc) + alloc_len - ivsize, iv, ivsize);
+               iv_dma = dma_map_single(dev, iv, ivsize, DMA_TO_DEVICE);
        }
        memset(&edesc->desc, 0, sizeof(edesc->desc));
 
@@ -1445,10 +1441,6 @@ static struct talitos_edesc *talitos_edesc_alloc(struct device *dev,
                                                     DMA_BIDIRECTIONAL);
        }
        return edesc;
-error_sg:
-       if (iv_dma)
-               dma_unmap_single(dev, iv_dma, ivsize, DMA_TO_DEVICE);
-       return err;
 }
 
 static struct talitos_edesc *aead_edesc_alloc(struct aead_request *areq, u8 *iv,
index 4e55768..fe69dcc 100644 (file)
@@ -203,6 +203,7 @@ struct at_xdmac_chan {
        u32                             save_cim;
        u32                             save_cnda;
        u32                             save_cndc;
+       u32                             irq_status;
        unsigned long                   status;
        struct tasklet_struct           tasklet;
        struct dma_slave_config         sconfig;
@@ -1580,8 +1581,8 @@ static void at_xdmac_tasklet(unsigned long data)
        struct at_xdmac_desc    *desc;
        u32                     error_mask;
 
-       dev_dbg(chan2dev(&atchan->chan), "%s: status=0x%08lx\n",
-                __func__, atchan->status);
+       dev_dbg(chan2dev(&atchan->chan), "%s: status=0x%08x\n",
+               __func__, atchan->irq_status);
 
        error_mask = AT_XDMAC_CIS_RBEIS
                     | AT_XDMAC_CIS_WBEIS
@@ -1589,15 +1590,15 @@ static void at_xdmac_tasklet(unsigned long data)
 
        if (at_xdmac_chan_is_cyclic(atchan)) {
                at_xdmac_handle_cyclic(atchan);
-       } else if ((atchan->status & AT_XDMAC_CIS_LIS)
-                  || (atchan->status & error_mask)) {
+       } else if ((atchan->irq_status & AT_XDMAC_CIS_LIS)
+                  || (atchan->irq_status & error_mask)) {
                struct dma_async_tx_descriptor  *txd;
 
-               if (atchan->status & AT_XDMAC_CIS_RBEIS)
+               if (atchan->irq_status & AT_XDMAC_CIS_RBEIS)
                        dev_err(chan2dev(&atchan->chan), "read bus error!!!");
-               if (atchan->status & AT_XDMAC_CIS_WBEIS)
+               if (atchan->irq_status & AT_XDMAC_CIS_WBEIS)
                        dev_err(chan2dev(&atchan->chan), "write bus error!!!");
-               if (atchan->status & AT_XDMAC_CIS_ROIS)
+               if (atchan->irq_status & AT_XDMAC_CIS_ROIS)
                        dev_err(chan2dev(&atchan->chan), "request overflow error!!!");
 
                spin_lock(&atchan->lock);
@@ -1652,7 +1653,7 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id)
                        atchan = &atxdmac->chan[i];
                        chan_imr = at_xdmac_chan_read(atchan, AT_XDMAC_CIM);
                        chan_status = at_xdmac_chan_read(atchan, AT_XDMAC_CIS);
-                       atchan->status = chan_status & chan_imr;
+                       atchan->irq_status = chan_status & chan_imr;
                        dev_vdbg(atxdmac->dma.dev,
                                 "%s: chan%d: imr=0x%x, status=0x%x\n",
                                 __func__, i, chan_imr, chan_status);
@@ -1666,7 +1667,7 @@ static irqreturn_t at_xdmac_interrupt(int irq, void *dev_id)
                                 at_xdmac_chan_read(atchan, AT_XDMAC_CDA),
                                 at_xdmac_chan_read(atchan, AT_XDMAC_CUBC));
 
-                       if (atchan->status & (AT_XDMAC_CIS_RBEIS | AT_XDMAC_CIS_WBEIS))
+                       if (atchan->irq_status & (AT_XDMAC_CIS_RBEIS | AT_XDMAC_CIS_WBEIS))
                                at_xdmac_write(atxdmac, AT_XDMAC_GD, atchan->mask);
 
                        tasklet_schedule(&atchan->tasklet);
index 1a44c80..ae10f56 100644 (file)
@@ -406,38 +406,32 @@ static void bcm2835_dma_fill_cb_chain_with_sg(
        }
 }
 
-static int bcm2835_dma_abort(void __iomem *chan_base)
+static int bcm2835_dma_abort(struct bcm2835_chan *c)
 {
-       unsigned long cs;
+       void __iomem *chan_base = c->chan_base;
        long int timeout = 10000;
 
-       cs = readl(chan_base + BCM2835_DMA_CS);
-       if (!(cs & BCM2835_DMA_ACTIVE))
+       /*
+        * A zero control block address means the channel is idle.
+        * (The ACTIVE flag in the CS register is not a reliable indicator.)
+        */
+       if (!readl(chan_base + BCM2835_DMA_ADDR))
                return 0;
 
        /* Write 0 to the active bit - Pause the DMA */
        writel(0, chan_base + BCM2835_DMA_CS);
 
        /* Wait for any current AXI transfer to complete */
-       while ((cs & BCM2835_DMA_ISPAUSED) && --timeout) {
+       while ((readl(chan_base + BCM2835_DMA_CS) &
+               BCM2835_DMA_WAITING_FOR_WRITES) && --timeout)
                cpu_relax();
-               cs = readl(chan_base + BCM2835_DMA_CS);
-       }
 
-       /* We'll un-pause when we set of our next DMA */
+       /* Peripheral might be stuck and fail to signal AXI write responses */
        if (!timeout)
-               return -ETIMEDOUT;
-
-       if (!(cs & BCM2835_DMA_ACTIVE))
-               return 0;
-
-       /* Terminate the control block chain */
-       writel(0, chan_base + BCM2835_DMA_NEXTCB);
-
-       /* Abort the whole DMA */
-       writel(BCM2835_DMA_ABORT | BCM2835_DMA_ACTIVE,
-              chan_base + BCM2835_DMA_CS);
+               dev_err(c->vc.chan.device->dev,
+                       "failed to complete outstanding writes\n");
 
+       writel(BCM2835_DMA_RESET, chan_base + BCM2835_DMA_CS);
        return 0;
 }
 
@@ -476,8 +470,15 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
 
        spin_lock_irqsave(&c->vc.lock, flags);
 
-       /* Acknowledge interrupt */
-       writel(BCM2835_DMA_INT, c->chan_base + BCM2835_DMA_CS);
+       /*
+        * Clear the INT flag to receive further interrupts. Keep the channel
+        * active in case the descriptor is cyclic or in case the client has
+        * already terminated the descriptor and issued a new one. (May happen
+        * if this IRQ handler is threaded.) If the channel is finished, it
+        * will remain idle despite the ACTIVE flag being set.
+        */
+       writel(BCM2835_DMA_INT | BCM2835_DMA_ACTIVE,
+              c->chan_base + BCM2835_DMA_CS);
 
        d = c->desc;
 
@@ -485,11 +486,7 @@ static irqreturn_t bcm2835_dma_callback(int irq, void *data)
                if (d->cyclic) {
                        /* call the cyclic callback */
                        vchan_cyclic_callback(&d->vd);
-
-                       /* Keep the DMA engine running */
-                       writel(BCM2835_DMA_ACTIVE,
-                              c->chan_base + BCM2835_DMA_CS);
-               } else {
+               } else if (!readl(c->chan_base + BCM2835_DMA_ADDR)) {
                        vchan_cookie_complete(&c->desc->vd);
                        bcm2835_dma_start_desc(c);
                }
@@ -779,7 +776,6 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan)
        struct bcm2835_chan *c = to_bcm2835_dma_chan(chan);
        struct bcm2835_dmadev *d = to_bcm2835_dma_dev(c->vc.chan.device);
        unsigned long flags;
-       int timeout = 10000;
        LIST_HEAD(head);
 
        spin_lock_irqsave(&c->vc.lock, flags);
@@ -789,27 +785,11 @@ static int bcm2835_dma_terminate_all(struct dma_chan *chan)
        list_del_init(&c->node);
        spin_unlock(&d->lock);
 
-       /*
-        * Stop DMA activity: we assume the callback will not be called
-        * after bcm_dma_abort() returns (even if it does, it will see
-        * c->desc is NULL and exit.)
-        */
+       /* stop DMA activity */
        if (c->desc) {
                vchan_terminate_vdesc(&c->desc->vd);
                c->desc = NULL;
-               bcm2835_dma_abort(c->chan_base);
-
-               /* Wait for stopping */
-               while (--timeout) {
-                       if (!(readl(c->chan_base + BCM2835_DMA_CS) &
-                                               BCM2835_DMA_ACTIVE))
-                               break;
-
-                       cpu_relax();
-               }
-
-               if (!timeout)
-                       dev_err(d->ddev.dev, "DMA transfer could not be terminated\n");
+               bcm2835_dma_abort(c);
        }
 
        vchan_get_all_descriptors(&c->vc, &head);
index 2eea4ef..6511928 100644 (file)
@@ -711,11 +711,9 @@ static int dmatest_func(void *data)
                        srcs[i] = um->addr[i] + src_off;
                        ret = dma_mapping_error(dev->dev, um->addr[i]);
                        if (ret) {
-                               dmaengine_unmap_put(um);
                                result("src mapping error", total_tests,
                                       src_off, dst_off, len, ret);
-                               failed_tests++;
-                               continue;
+                               goto error_unmap_continue;
                        }
                        um->to_cnt++;
                }
@@ -730,11 +728,9 @@ static int dmatest_func(void *data)
                                               DMA_BIDIRECTIONAL);
                        ret = dma_mapping_error(dev->dev, dsts[i]);
                        if (ret) {
-                               dmaengine_unmap_put(um);
                                result("dst mapping error", total_tests,
                                       src_off, dst_off, len, ret);
-                               failed_tests++;
-                               continue;
+                               goto error_unmap_continue;
                        }
                        um->bidi_cnt++;
                }
@@ -762,12 +758,10 @@ static int dmatest_func(void *data)
                }
 
                if (!tx) {
-                       dmaengine_unmap_put(um);
                        result("prep error", total_tests, src_off,
                               dst_off, len, ret);
                        msleep(100);
-                       failed_tests++;
-                       continue;
+                       goto error_unmap_continue;
                }
 
                done->done = false;
@@ -776,12 +770,10 @@ static int dmatest_func(void *data)
                cookie = tx->tx_submit(tx);
 
                if (dma_submit_error(cookie)) {
-                       dmaengine_unmap_put(um);
                        result("submit error", total_tests, src_off,
                               dst_off, len, ret);
                        msleep(100);
-                       failed_tests++;
-                       continue;
+                       goto error_unmap_continue;
                }
                dma_async_issue_pending(chan);
 
@@ -790,22 +782,20 @@ static int dmatest_func(void *data)
 
                status = dma_async_is_tx_complete(chan, cookie, NULL, NULL);
 
-               dmaengine_unmap_put(um);
-
                if (!done->done) {
                        result("test timed out", total_tests, src_off, dst_off,
                               len, 0);
-                       failed_tests++;
-                       continue;
+                       goto error_unmap_continue;
                } else if (status != DMA_COMPLETE) {
                        result(status == DMA_ERROR ?
                               "completion error status" :
                               "completion busy status", total_tests, src_off,
                               dst_off, len, ret);
-                       failed_tests++;
-                       continue;
+                       goto error_unmap_continue;
                }
 
+               dmaengine_unmap_put(um);
+
                if (params->noverify) {
                        verbose_result("test passed", total_tests, src_off,
                                       dst_off, len, 0);
@@ -846,6 +836,12 @@ static int dmatest_func(void *data)
                        verbose_result("test passed", total_tests, src_off,
                                       dst_off, len, 0);
                }
+
+               continue;
+
+error_unmap_continue:
+               dmaengine_unmap_put(um);
+               failed_tests++;
        }
        ktime = ktime_sub(ktime_get(), ktime);
        ktime = ktime_sub(ktime, comparetime);
index c2fff3f..4a09af3 100644 (file)
@@ -618,7 +618,7 @@ static void imxdma_tasklet(unsigned long data)
 {
        struct imxdma_channel *imxdmac = (void *)data;
        struct imxdma_engine *imxdma = imxdmac->imxdma;
-       struct imxdma_desc *desc;
+       struct imxdma_desc *desc, *next_desc;
        unsigned long flags;
 
        spin_lock_irqsave(&imxdma->lock, flags);
@@ -648,10 +648,10 @@ static void imxdma_tasklet(unsigned long data)
        list_move_tail(imxdmac->ld_active.next, &imxdmac->ld_free);
 
        if (!list_empty(&imxdmac->ld_queue)) {
-               desc = list_first_entry(&imxdmac->ld_queue, struct imxdma_desc,
-                                       node);
+               next_desc = list_first_entry(&imxdmac->ld_queue,
+                                            struct imxdma_desc, node);
                list_move_tail(imxdmac->ld_queue.next, &imxdmac->ld_active);
-               if (imxdma_xfer_desc(desc) < 0)
+               if (imxdma_xfer_desc(next_desc) < 0)
                        dev_warn(imxdma->dev, "%s: channel: %d couldn't xfer desc\n",
                                 __func__, imxdmac->channel);
        }
index a2b0a0e..86708fb 100644 (file)
@@ -1182,8 +1182,8 @@ static int sdma_request_channel0(struct sdma_engine *sdma)
 {
        int ret = -EBUSY;
 
-       sdma->bd0 = dma_zalloc_coherent(NULL, PAGE_SIZE, &sdma->bd0_phys,
-                                       GFP_NOWAIT);
+       sdma->bd0 = dma_alloc_coherent(NULL, PAGE_SIZE, &sdma->bd0_phys,
+                                      GFP_NOWAIT);
        if (!sdma->bd0) {
                ret = -ENOMEM;
                goto out;
@@ -1205,8 +1205,8 @@ static int sdma_alloc_bd(struct sdma_desc *desc)
        u32 bd_size = desc->num_bd * sizeof(struct sdma_buffer_descriptor);
        int ret = 0;
 
-       desc->bd = dma_zalloc_coherent(NULL, bd_size, &desc->bd_phys,
-                                       GFP_NOWAIT);
+       desc->bd = dma_alloc_coherent(NULL, bd_size, &desc->bd_phys,
+                                     GFP_NOWAIT);
        if (!desc->bd) {
                ret = -ENOMEM;
                goto out;
index b7ec56a..1a2028e 100644 (file)
@@ -325,8 +325,8 @@ static int mtk_hsdma_alloc_pchan(struct mtk_hsdma_device *hsdma,
         * and [MTK_DMA_SIZE ... 2 * MTK_DMA_SIZE - 1] is for RX ring.
         */
        pc->sz_ring = 2 * MTK_DMA_SIZE * sizeof(*ring->txd);
-       ring->txd = dma_zalloc_coherent(hsdma2dev(hsdma), pc->sz_ring,
-                                       &ring->tphys, GFP_NOWAIT);
+       ring->txd = dma_alloc_coherent(hsdma2dev(hsdma), pc->sz_ring,
+                                      &ring->tphys, GFP_NOWAIT);
        if (!ring->txd)
                return -ENOMEM;
 
index 35193b3..22cc7f6 100644 (file)
@@ -416,9 +416,9 @@ static int mxs_dma_alloc_chan_resources(struct dma_chan *chan)
        struct mxs_dma_engine *mxs_dma = mxs_chan->mxs_dma;
        int ret;
 
-       mxs_chan->ccw = dma_zalloc_coherent(mxs_dma->dma_device.dev,
-                                           CCW_BLOCK_SIZE,
-                                           &mxs_chan->ccw_phys, GFP_KERNEL);
+       mxs_chan->ccw = dma_alloc_coherent(mxs_dma->dma_device.dev,
+                                          CCW_BLOCK_SIZE,
+                                          &mxs_chan->ccw_phys, GFP_KERNEL);
        if (!mxs_chan->ccw) {
                ret = -ENOMEM;
                goto err_alloc;
index 1d59888..eafd6c4 100644 (file)
@@ -1208,8 +1208,8 @@ static int xgene_dma_create_ring_one(struct xgene_dma_chan *chan,
        ring->size = ret;
 
        /* Allocate memory for DMA ring descriptor */
-       ring->desc_vaddr = dma_zalloc_coherent(chan->dev, ring->size,
-                                              &ring->desc_paddr, GFP_KERNEL);
+       ring->desc_vaddr = dma_alloc_coherent(chan->dev, ring->size,
+                                             &ring->desc_paddr, GFP_KERNEL);
        if (!ring->desc_vaddr) {
                chan_err(chan, "Failed to allocate ring desc\n");
                return -ENOMEM;
index 0288096..cb20b41 100644 (file)
@@ -879,10 +879,9 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
         */
        if (chan->xdev->dma_config->dmatype == XDMA_TYPE_AXIDMA) {
                /* Allocate the buffer descriptors. */
-               chan->seg_v = dma_zalloc_coherent(chan->dev,
-                                                 sizeof(*chan->seg_v) *
-                                                 XILINX_DMA_NUM_DESCS,
-                                                 &chan->seg_p, GFP_KERNEL);
+               chan->seg_v = dma_alloc_coherent(chan->dev,
+                                                sizeof(*chan->seg_v) * XILINX_DMA_NUM_DESCS,
+                                                &chan->seg_p, GFP_KERNEL);
                if (!chan->seg_v) {
                        dev_err(chan->dev,
                                "unable to allocate channel %d descriptors\n",
@@ -895,9 +894,10 @@ static int xilinx_dma_alloc_chan_resources(struct dma_chan *dchan)
                 * so allocating a desc segment during channel allocation for
                 * programming tail descriptor.
                 */
-               chan->cyclic_seg_v = dma_zalloc_coherent(chan->dev,
-                                       sizeof(*chan->cyclic_seg_v),
-                                       &chan->cyclic_seg_p, GFP_KERNEL);
+               chan->cyclic_seg_v = dma_alloc_coherent(chan->dev,
+                                                       sizeof(*chan->cyclic_seg_v),
+                                                       &chan->cyclic_seg_p,
+                                                       GFP_KERNEL);
                if (!chan->cyclic_seg_v) {
                        dev_err(chan->dev,
                                "unable to allocate desc segment for cyclic DMA\n");
index 8db5175..4478787 100644 (file)
@@ -490,9 +490,9 @@ static int zynqmp_dma_alloc_chan_resources(struct dma_chan *dchan)
                list_add_tail(&desc->node, &chan->free_list);
        }
 
-       chan->desc_pool_v = dma_zalloc_coherent(chan->dev,
-                               (2 * chan->desc_size * ZYNQMP_DMA_NUM_DESCS),
-                               &chan->desc_pool_p, GFP_KERNEL);
+       chan->desc_pool_v = dma_alloc_coherent(chan->dev,
+                                              (2 * chan->desc_size * ZYNQMP_DMA_NUM_DESCS),
+                                              &chan->desc_pool_p, GFP_KERNEL);
        if (!chan->desc_pool_v)
                return -ENOMEM;
 
index 4213cb0..f8664ba 100644 (file)
@@ -295,8 +295,8 @@ struct altr_sdram_mc_data {
 #define S10_SYSMGR_ECC_INTSTAT_DERR_OFST  0xA0
 
 /* Sticky registers for Uncorrected Errors */
-#define S10_SYSMGR_UE_VAL_OFST            0x120
-#define S10_SYSMGR_UE_ADDR_OFST           0x124
+#define S10_SYSMGR_UE_VAL_OFST            0x220
+#define S10_SYSMGR_UE_ADDR_OFST           0x224
 
 #define S10_DDR0_IRQ_MASK                 BIT(16)
 
index 09b845e..a785ffd 100644 (file)
@@ -1144,10 +1144,6 @@ static int sbp2_probe(struct fw_unit *unit, const struct ieee1394_device_id *id)
        if (device->is_local)
                return -ENODEV;
 
-       if (dma_get_max_seg_size(device->card->device) > SBP2_MAX_SEG_SIZE)
-               WARN_ON(dma_set_max_seg_size(device->card->device,
-                                            SBP2_MAX_SEG_SIZE));
-
        shost = scsi_host_alloc(&scsi_driver_template, sizeof(*tgt));
        if (shost == NULL)
                return -ENOMEM;
@@ -1610,6 +1606,7 @@ static struct scsi_host_template scsi_driver_template = {
        .eh_abort_handler       = sbp2_scsi_abort,
        .this_id                = -1,
        .sg_tablesize           = SG_ALL,
+       .max_segment_size       = SBP2_MAX_SEG_SIZE,
        .can_queue              = 1,
        .sdev_attrs             = sbp2_scsi_sysfs_attrs,
 };
index 472c88a..92f843e 100644 (file)
@@ -119,6 +119,11 @@ void scmi_driver_unregister(struct scmi_driver *driver)
 }
 EXPORT_SYMBOL_GPL(scmi_driver_unregister);
 
+static void scmi_device_release(struct device *dev)
+{
+       kfree(to_scmi_dev(dev));
+}
+
 struct scmi_device *
 scmi_device_create(struct device_node *np, struct device *parent, int protocol)
 {
@@ -138,6 +143,7 @@ scmi_device_create(struct device_node *np, struct device *parent, int protocol)
        scmi_dev->dev.parent = parent;
        scmi_dev->dev.of_node = np;
        scmi_dev->dev.bus = &scmi_bus_type;
+       scmi_dev->dev.release = scmi_device_release;
        dev_set_name(&scmi_dev->dev, "scmi_dev.%d", id);
 
        retval = device_register(&scmi_dev->dev);
@@ -156,9 +162,8 @@ free_mem:
 void scmi_device_destroy(struct scmi_device *scmi_dev)
 {
        scmi_handle_put(scmi_dev->handle);
-       device_unregister(&scmi_dev->dev);
        ida_simple_remove(&scmi_bus_id, scmi_dev->id);
-       kfree(scmi_dev);
+       device_unregister(&scmi_dev->dev);
 }
 
 void scmi_set_handle(struct scmi_device *scmi_dev)
index 23ea1ed..352bd24 100644 (file)
@@ -37,8 +37,9 @@ extern u64 efi_system_table;
 static struct ptdump_info efi_ptdump_info = {
        .mm             = &efi_mm,
        .markers        = (struct addr_marker[]){
-               { 0,            "UEFI runtime start" },
-               { DEFAULT_MAP_WINDOW_64, "UEFI runtime end" }
+               { 0,                            "UEFI runtime start" },
+               { DEFAULT_MAP_WINDOW_64,        "UEFI runtime end" },
+               { -1,                           NULL }
        },
        .base_addr      = 0,
 };
index 4c46ff6..55b77c5 100644 (file)
@@ -592,11 +592,7 @@ int __init efi_config_parse_tables(void *config_tables, int count, int sz,
 
                early_memunmap(tbl, sizeof(*tbl));
        }
-       return 0;
-}
 
-int __init efi_apply_persistent_mem_reservations(void)
-{
        if (efi.mem_reserve != EFI_INVALID_TABLE_ADDR) {
                unsigned long prsv = efi.mem_reserve;
 
index eee42d5..c037c6c 100644 (file)
@@ -75,9 +75,6 @@ void install_memreserve_table(efi_system_table_t *sys_table_arg)
        efi_guid_t memreserve_table_guid = LINUX_EFI_MEMRESERVE_TABLE_GUID;
        efi_status_t status;
 
-       if (IS_ENABLED(CONFIG_ARM))
-               return;
-
        status = efi_call_early(allocate_pool, EFI_LOADER_DATA, sizeof(*rsv),
                                (void **)&rsv);
        if (status != EFI_SUCCESS) {
index 8903b9c..e2abfdb 100644 (file)
@@ -146,6 +146,13 @@ void efi_call_virt_check_flags(unsigned long flags, const char *call)
  */
 static DEFINE_SEMAPHORE(efi_runtime_lock);
 
+/*
+ * Expose the EFI runtime lock to the UV platform
+ */
+#ifdef CONFIG_X86_UV
+extern struct semaphore __efi_uv_runtime_lock __alias(efi_runtime_lock);
+#endif
+
 /*
  * Calls the appropriate efi_runtime_service() with the appropriate
  * arguments.
index a1a09e0..13851b3 100644 (file)
@@ -508,14 +508,11 @@ static int __init s10_init(void)
                return -ENODEV;
 
        np = of_find_matching_node(fw_np, s10_of_match);
-       if (!np) {
-               of_node_put(fw_np);
+       if (!np)
                return -ENODEV;
-       }
 
        of_node_put(np);
        ret = of_platform_populate(fw_np, s10_of_match, NULL, NULL);
-       of_node_put(fw_np);
        if (ret)
                return ret;
 
index 6b11f13..7f9e030 100644 (file)
@@ -66,8 +66,10 @@ static int altr_a10sr_gpio_direction_input(struct gpio_chip *gc,
 static int altr_a10sr_gpio_direction_output(struct gpio_chip *gc,
                                            unsigned int nr, int value)
 {
-       if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT))
+       if (nr <= (ALTR_A10SR_OUT_VALID_RANGE_HI - ALTR_A10SR_LED_VALID_SHIFT)) {
+               altr_a10sr_gpio_set(gc, nr, value);
                return 0;
+       }
        return -EINVAL;
 }
 
index e0d6a0a..e41223c 100644 (file)
@@ -180,7 +180,18 @@ static void sprd_eic_free(struct gpio_chip *chip, unsigned int offset)
 
 static int sprd_eic_get(struct gpio_chip *chip, unsigned int offset)
 {
-       return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA);
+       struct sprd_eic *sprd_eic = gpiochip_get_data(chip);
+
+       switch (sprd_eic->type) {
+       case SPRD_EIC_DEBOUNCE:
+               return sprd_eic_read(chip, offset, SPRD_EIC_DBNC_DATA);
+       case SPRD_EIC_ASYNC:
+               return sprd_eic_read(chip, offset, SPRD_EIC_ASYNC_DATA);
+       case SPRD_EIC_SYNC:
+               return sprd_eic_read(chip, offset, SPRD_EIC_SYNC_DATA);
+       default:
+               return -ENOTSUPP;
+       }
 }
 
 static int sprd_eic_direction_input(struct gpio_chip *chip, unsigned int offset)
@@ -368,6 +379,7 @@ static int sprd_eic_irq_set_type(struct irq_data *data, unsigned int flow_type)
                        irq_set_handler_locked(data, handle_edge_irq);
                        break;
                case IRQ_TYPE_EDGE_BOTH:
+                       sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTMODE, 0);
                        sprd_eic_update(chip, offset, SPRD_EIC_ASYNC_INTBOTH, 1);
                        irq_set_handler_locked(data, handle_edge_irq);
                        break;
index 00e954f..74401e0 100644 (file)
@@ -30,6 +30,7 @@
 #define GPIO_REG_EDGE          0xA0
 
 struct mtk_gc {
+       struct irq_chip irq_chip;
        struct gpio_chip chip;
        spinlock_t lock;
        int bank;
@@ -189,13 +190,6 @@ mediatek_gpio_irq_type(struct irq_data *d, unsigned int type)
        return 0;
 }
 
-static struct irq_chip mediatek_gpio_irq_chip = {
-       .irq_unmask             = mediatek_gpio_irq_unmask,
-       .irq_mask               = mediatek_gpio_irq_mask,
-       .irq_mask_ack           = mediatek_gpio_irq_mask,
-       .irq_set_type           = mediatek_gpio_irq_type,
-};
-
 static int
 mediatek_gpio_xlate(struct gpio_chip *chip,
                    const struct of_phandle_args *spec, u32 *flags)
@@ -254,6 +248,13 @@ mediatek_gpio_bank_probe(struct device *dev,
                return ret;
        }
 
+       rg->irq_chip.name = dev_name(dev);
+       rg->irq_chip.parent_device = dev;
+       rg->irq_chip.irq_unmask = mediatek_gpio_irq_unmask;
+       rg->irq_chip.irq_mask = mediatek_gpio_irq_mask;
+       rg->irq_chip.irq_mask_ack = mediatek_gpio_irq_mask;
+       rg->irq_chip.irq_set_type = mediatek_gpio_irq_type;
+
        if (mtk->gpio_irq) {
                /*
                 * Manually request the irq here instead of passing
@@ -270,14 +271,14 @@ mediatek_gpio_bank_probe(struct device *dev,
                        return ret;
                }
 
-               ret = gpiochip_irqchip_add(&rg->chip, &mediatek_gpio_irq_chip,
+               ret = gpiochip_irqchip_add(&rg->chip, &rg->irq_chip,
                                           0, handle_simple_irq, IRQ_TYPE_NONE);
                if (ret) {
                        dev_err(dev, "failed to add gpiochip_irqchip\n");
                        return ret;
                }
 
-               gpiochip_set_chained_irqchip(&rg->chip, &mediatek_gpio_irq_chip,
+               gpiochip_set_chained_irqchip(&rg->chip, &rg->irq_chip,
                                             mtk->gpio_irq, NULL);
        }
 
@@ -310,7 +311,6 @@ mediatek_gpio_probe(struct platform_device *pdev)
        mtk->gpio_irq = irq_of_parse_and_map(np, 0);
        mtk->dev = dev;
        platform_set_drvdata(pdev, mtk);
-       mediatek_gpio_irq_chip.name = dev_name(dev);
 
        for (i = 0; i < MTK_BANK_CNT; i++) {
                ret = mediatek_gpio_bank_probe(dev, np, i);
index 83617fd..0dc9641 100644 (file)
@@ -289,7 +289,7 @@ static bool pca953x_volatile_register(struct device *dev, unsigned int reg)
        return pca953x_check_register(chip, reg, bank);
 }
 
-const struct regmap_config pca953x_i2c_regmap = {
+static const struct regmap_config pca953x_i2c_regmap = {
        .reg_bits = 8,
        .val_bits = 8,
 
index adf72dd..68a35b6 100644 (file)
@@ -84,6 +84,7 @@ MODULE_DEVICE_TABLE(of, pcf857x_of_table);
  */
 struct pcf857x {
        struct gpio_chip        chip;
+       struct irq_chip         irqchip;
        struct i2c_client       *client;
        struct mutex            lock;           /* protect 'out' */
        unsigned                out;            /* software latch */
@@ -252,18 +253,6 @@ static void pcf857x_irq_bus_sync_unlock(struct irq_data *data)
        mutex_unlock(&gpio->lock);
 }
 
-static struct irq_chip pcf857x_irq_chip = {
-       .name           = "pcf857x",
-       .irq_enable     = pcf857x_irq_enable,
-       .irq_disable    = pcf857x_irq_disable,
-       .irq_ack        = noop,
-       .irq_mask       = noop,
-       .irq_unmask     = noop,
-       .irq_set_wake   = pcf857x_irq_set_wake,
-       .irq_bus_lock           = pcf857x_irq_bus_lock,
-       .irq_bus_sync_unlock    = pcf857x_irq_bus_sync_unlock,
-};
-
 /*-------------------------------------------------------------------------*/
 
 static int pcf857x_probe(struct i2c_client *client,
@@ -376,8 +365,17 @@ static int pcf857x_probe(struct i2c_client *client,
 
        /* Enable irqchip if we have an interrupt */
        if (client->irq) {
+               gpio->irqchip.name = "pcf857x",
+               gpio->irqchip.irq_enable = pcf857x_irq_enable,
+               gpio->irqchip.irq_disable = pcf857x_irq_disable,
+               gpio->irqchip.irq_ack = noop,
+               gpio->irqchip.irq_mask = noop,
+               gpio->irqchip.irq_unmask = noop,
+               gpio->irqchip.irq_set_wake = pcf857x_irq_set_wake,
+               gpio->irqchip.irq_bus_lock = pcf857x_irq_bus_lock,
+               gpio->irqchip.irq_bus_sync_unlock = pcf857x_irq_bus_sync_unlock,
                status = gpiochip_irqchip_add_nested(&gpio->chip,
-                                                    &pcf857x_irq_chip,
+                                                    &gpio->irqchip,
                                                     0, handle_level_irq,
                                                     IRQ_TYPE_NONE);
                if (status) {
@@ -392,7 +390,7 @@ static int pcf857x_probe(struct i2c_client *client,
                if (status)
                        goto fail;
 
-               gpiochip_set_nested_irqchip(&gpio->chip, &pcf857x_irq_chip,
+               gpiochip_set_nested_irqchip(&gpio->chip, &gpio->irqchip,
                                            client->irq);
                gpio->irq_parent = client->irq;
        }
index e9600b5..bcc6be4 100644 (file)
@@ -245,6 +245,7 @@ static bool pxa_gpio_has_pinctrl(void)
 {
        switch (gpio_type) {
        case PXA3XX_GPIO:
+       case MMP2_GPIO:
                return false;
 
        default:
index 1b79ebc..541fa6a 100644 (file)
@@ -253,6 +253,7 @@ static int vf610_gpio_probe(struct platform_device *pdev)
        struct vf610_gpio_port *port;
        struct resource *iores;
        struct gpio_chip *gc;
+       int i;
        int ret;
 
        port = devm_kzalloc(&pdev->dev, sizeof(*port), GFP_KERNEL);
@@ -319,6 +320,10 @@ static int vf610_gpio_probe(struct platform_device *pdev)
        if (ret < 0)
                return ret;
 
+       /* Mask all GPIO interrupts */
+       for (i = 0; i < gc->ngpio; i++)
+               vf610_gpio_writel(0, port->base + PORT_PCR(i));
+
        /* Clear the interrupt status register for all GPIO's */
        vf610_gpio_writel(~0, port->base + PORT_ISFR);
 
index 48534bd..259cf6a 100644 (file)
@@ -357,8 +357,6 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
        mutex_unlock(&acpi_gpio_deferred_req_irqs_lock);
 
        list_for_each_entry_safe_reverse(event, ep, &acpi_gpio->events, node) {
-               struct gpio_desc *desc;
-
                if (event->irq_requested) {
                        if (event->irq_is_wake)
                                disable_irq_wake(event->irq);
@@ -366,11 +364,8 @@ void acpi_gpiochip_free_interrupts(struct gpio_chip *chip)
                        free_irq(event->irq, event);
                }
 
-               desc = event->desc;
-               if (WARN_ON(IS_ERR(desc)))
-                       continue;
                gpiochip_unlock_as_irq(chip, event->pin);
-               gpiochip_free_own_desc(desc);
+               gpiochip_free_own_desc(event->desc);
                list_del(&event->node);
                kfree(event);
        }
index 1651d7f..d1adfdf 100644 (file)
@@ -828,7 +828,14 @@ static irqreturn_t lineevent_irq_thread(int irq, void *p)
        /* Do not leak kernel stack to userspace */
        memset(&ge, 0, sizeof(ge));
 
-       ge.timestamp = le->timestamp;
+       /*
+        * We may be running from a nested threaded interrupt in which case
+        * we didn't get the timestamp from lineevent_irq_handler().
+        */
+       if (!le->timestamp)
+               ge.timestamp = ktime_get_real_ns();
+       else
+               ge.timestamp = le->timestamp;
 
        if (le->eflags & GPIOEVENT_REQUEST_RISING_EDGE
            && le->eflags & GPIOEVENT_REQUEST_FALLING_EDGE) {
index a028661..92b11de 100644 (file)
@@ -576,6 +576,7 @@ static const struct amdgpu_px_quirk amdgpu_px_quirk_list[] = {
        { 0x1002, 0x6900, 0x1028, 0x0812, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0x1002, 0x6900, 0x1028, 0x0813, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0x1002, 0x6900, 0x1025, 0x125A, AMDGPU_PX_QUIRK_FORCE_ATPX },
+       { 0x1002, 0x6900, 0x17AA, 0x3806, AMDGPU_PX_QUIRK_FORCE_ATPX },
        { 0, 0, 0, 0, 0 },
 };
 
index 8a078f4..7ff3a28 100644 (file)
@@ -1701,8 +1701,10 @@ static int amdgpu_device_ip_init(struct amdgpu_device *adev)
                amdgpu_xgmi_add_device(adev);
        amdgpu_amdkfd_device_init(adev);
 
-       if (amdgpu_sriov_vf(adev))
+       if (amdgpu_sriov_vf(adev)) {
+               amdgpu_virt_init_data_exchange(adev);
                amdgpu_virt_release_full_gpu(adev, true);
+       }
 
        return 0;
 }
@@ -2632,9 +2634,6 @@ fence_driver_init:
                goto failed;
        }
 
-       if (amdgpu_sriov_vf(adev))
-               amdgpu_virt_init_data_exchange(adev);
-
        amdgpu_fbdev_init(adev);
 
        r = amdgpu_pm_sysfs_init(adev);
@@ -2798,7 +2797,7 @@ int amdgpu_device_suspend(struct drm_device *dev, bool suspend, bool fbcon)
                        struct drm_framebuffer *fb = crtc->primary->fb;
                        struct amdgpu_bo *robj;
 
-                       if (amdgpu_crtc->cursor_bo) {
+                       if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
                                struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
                                r = amdgpu_bo_reserve(aobj, true);
                                if (r == 0) {
@@ -2906,7 +2905,7 @@ int amdgpu_device_resume(struct drm_device *dev, bool resume, bool fbcon)
                list_for_each_entry(crtc, &dev->mode_config.crtc_list, head) {
                        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 
-                       if (amdgpu_crtc->cursor_bo) {
+                       if (amdgpu_crtc->cursor_bo && !adev->enable_virtual_display) {
                                struct amdgpu_bo *aobj = gem_to_amdgpu_bo(amdgpu_crtc->cursor_bo);
                                r = amdgpu_bo_reserve(aobj, true);
                                if (r == 0) {
@@ -3226,6 +3225,7 @@ static int amdgpu_device_reset_sriov(struct amdgpu_device *adev,
        r = amdgpu_ib_ring_tests(adev);
 
 error:
+       amdgpu_virt_init_data_exchange(adev);
        amdgpu_virt_release_full_gpu(adev, true);
        if (!r && adev->virt.gim_feature & AMDGIM_FEATURE_GIM_FLR_VRAMLOST) {
                atomic_inc(&adev->vram_lost_counter);
index 15ce7e6..b083b21 100644 (file)
@@ -188,10 +188,12 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
                goto cleanup;
        }
 
-       r = amdgpu_bo_pin(new_abo, amdgpu_display_supported_domains(adev));
-       if (unlikely(r != 0)) {
-               DRM_ERROR("failed to pin new abo buffer before flip\n");
-               goto unreserve;
+       if (!adev->enable_virtual_display) {
+               r = amdgpu_bo_pin(new_abo, amdgpu_display_supported_domains(adev));
+               if (unlikely(r != 0)) {
+                       DRM_ERROR("failed to pin new abo buffer before flip\n");
+                       goto unreserve;
+               }
        }
 
        r = amdgpu_ttm_alloc_gart(&new_abo->tbo);
@@ -211,7 +213,8 @@ int amdgpu_display_crtc_page_flip_target(struct drm_crtc *crtc,
        amdgpu_bo_get_tiling_flags(new_abo, &tiling_flags);
        amdgpu_bo_unreserve(new_abo);
 
-       work->base = amdgpu_bo_gpu_offset(new_abo);
+       if (!adev->enable_virtual_display)
+               work->base = amdgpu_bo_gpu_offset(new_abo);
        work->target_vblank = target - (uint32_t)drm_crtc_vblank_count(crtc) +
                amdgpu_get_vblank_counter_kms(dev, work->crtc_id);
 
@@ -242,9 +245,10 @@ pflip_cleanup:
                goto cleanup;
        }
 unpin:
-       if (unlikely(amdgpu_bo_unpin(new_abo) != 0)) {
-               DRM_ERROR("failed to unpin new abo in error path\n");
-       }
+       if (!adev->enable_virtual_display)
+               if (unlikely(amdgpu_bo_unpin(new_abo) != 0))
+                       DRM_ERROR("failed to unpin new abo in error path\n");
+
 unreserve:
        amdgpu_bo_unreserve(new_abo);
 
index bc62bf4..5dc3491 100644 (file)
@@ -212,6 +212,7 @@ int amdgpu_driver_load_kms(struct drm_device *dev, unsigned long flags)
        }
 
        if (amdgpu_device_is_px(dev)) {
+               dev_pm_set_driver_flags(dev->dev, DPM_FLAG_NEVER_SKIP);
                pm_runtime_use_autosuspend(dev->dev);
                pm_runtime_set_autosuspend_delay(dev->dev, 5000);
                pm_runtime_set_active(dev->dev);
index 1f61ed9..0ed41a9 100644 (file)
@@ -1686,7 +1686,8 @@ static umode_t hwmon_attributes_visible(struct kobject *kobj,
                effective_mode &= ~S_IWUSR;
 
        if ((adev->flags & AMD_IS_APU) &&
-           (attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||
+           (attr == &sensor_dev_attr_power1_average.dev_attr.attr ||
+            attr == &sensor_dev_attr_power1_cap_max.dev_attr.attr ||
             attr == &sensor_dev_attr_power1_cap_min.dev_attr.attr||
             attr == &sensor_dev_attr_power1_cap.dev_attr.attr))
                return 0;
@@ -2008,6 +2009,7 @@ void amdgpu_pm_print_power_states(struct amdgpu_device *adev)
 
 int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
 {
+       struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
        int ret;
 
        if (adev->pm.sysfs_initialized)
@@ -2091,12 +2093,14 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
                                "pp_power_profile_mode\n");
                return ret;
        }
-       ret = device_create_file(adev->dev,
-                       &dev_attr_pp_od_clk_voltage);
-       if (ret) {
-               DRM_ERROR("failed to create device file "
-                               "pp_od_clk_voltage\n");
-               return ret;
+       if (hwmgr->od_enabled) {
+               ret = device_create_file(adev->dev,
+                               &dev_attr_pp_od_clk_voltage);
+               if (ret) {
+                       DRM_ERROR("failed to create device file "
+                                       "pp_od_clk_voltage\n");
+                       return ret;
+               }
        }
        ret = device_create_file(adev->dev,
                        &dev_attr_gpu_busy_percent);
@@ -2118,6 +2122,8 @@ int amdgpu_pm_sysfs_init(struct amdgpu_device *adev)
 
 void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
 {
+       struct pp_hwmgr *hwmgr = adev->powerplay.pp_handle;
+
        if (adev->pm.dpm_enabled == 0)
                return;
 
@@ -2138,8 +2144,9 @@ void amdgpu_pm_sysfs_fini(struct amdgpu_device *adev)
        device_remove_file(adev->dev, &dev_attr_pp_mclk_od);
        device_remove_file(adev->dev,
                        &dev_attr_pp_power_profile_mode);
-       device_remove_file(adev->dev,
-                       &dev_attr_pp_od_clk_voltage);
+       if (hwmgr->od_enabled)
+               device_remove_file(adev->dev,
+                               &dev_attr_pp_od_clk_voltage);
        device_remove_file(adev->dev, &dev_attr_gpu_busy_percent);
 }
 
index 71913a1..a38e0fb 100644 (file)
@@ -38,6 +38,7 @@
 #include "amdgpu_gem.h"
 #include <drm/amdgpu_drm.h>
 #include <linux/dma-buf.h>
+#include <linux/dma-fence-array.h>
 
 /**
  * amdgpu_gem_prime_get_sg_table - &drm_driver.gem_prime_get_sg_table
@@ -187,6 +188,48 @@ error:
        return ERR_PTR(ret);
 }
 
+static int
+__reservation_object_make_exclusive(struct reservation_object *obj)
+{
+       struct dma_fence **fences;
+       unsigned int count;
+       int r;
+
+       if (!reservation_object_get_list(obj)) /* no shared fences to convert */
+               return 0;
+
+       r = reservation_object_get_fences_rcu(obj, NULL, &count, &fences);
+       if (r)
+               return r;
+
+       if (count == 0) {
+               /* Now that was unexpected. */
+       } else if (count == 1) {
+               reservation_object_add_excl_fence(obj, fences[0]);
+               dma_fence_put(fences[0]);
+               kfree(fences);
+       } else {
+               struct dma_fence_array *array;
+
+               array = dma_fence_array_create(count, fences,
+                                              dma_fence_context_alloc(1), 0,
+                                              false);
+               if (!array)
+                       goto err_fences_put;
+
+               reservation_object_add_excl_fence(obj, &array->base);
+               dma_fence_put(&array->base);
+       }
+
+       return 0;
+
+err_fences_put:
+       while (count--)
+               dma_fence_put(fences[count]);
+       kfree(fences);
+       return -ENOMEM;
+}
+
 /**
  * amdgpu_gem_map_attach - &dma_buf_ops.attach implementation
  * @dma_buf: Shared DMA buffer
@@ -218,16 +261,16 @@ static int amdgpu_gem_map_attach(struct dma_buf *dma_buf,
 
        if (attach->dev->driver != adev->dev->driver) {
                /*
-                * Wait for all shared fences to complete before we switch to future
-                * use of exclusive fence on this prime shared bo.
+                * We only create shared fences for internal use, but importers
+                * of the dmabuf rely on exclusive fences for implicitly
+                * tracking write hazards. As any of the current fences may
+                * correspond to a write, we need to convert all existing
+                * fences on the reservation object into a single exclusive
+                * fence.
                 */
-               r = reservation_object_wait_timeout_rcu(bo->tbo.resv,
-                                                       true, false,
-                                                       MAX_SCHEDULE_TIMEOUT);
-               if (unlikely(r < 0)) {
-                       DRM_DEBUG_PRIME("Fence wait failed: %li\n", r);
+               r = __reservation_object_make_exclusive(bo->tbo.resv);
+               if (r)
                        goto error_unreserve;
-               }
        }
 
        /* pin buffer into GTT */
index 8fab0d6..3a9b48b 100644 (file)
@@ -90,8 +90,10 @@ static int psp_sw_fini(void *handle)
        adev->psp.sos_fw = NULL;
        release_firmware(adev->psp.asd_fw);
        adev->psp.asd_fw = NULL;
-       release_firmware(adev->psp.ta_fw);
-       adev->psp.ta_fw = NULL;
+       if (adev->psp.ta_fw) {
+               release_firmware(adev->psp.ta_fw);
+               adev->psp.ta_fw = NULL;
+       }
        return 0;
 }
 
@@ -435,6 +437,9 @@ static int psp_xgmi_initialize(struct psp_context *psp)
        struct ta_xgmi_shared_memory *xgmi_cmd;
        int ret;
 
+       if (!psp->adev->psp.ta_fw)
+               return -ENOENT;
+
        if (!psp->xgmi_context.initialized) {
                ret = psp_xgmi_init_shared_buf(psp);
                if (ret)
index e73d152..698bcb8 100644 (file)
@@ -638,12 +638,14 @@ void amdgpu_vm_move_to_lru_tail(struct amdgpu_device *adev,
        struct ttm_bo_global *glob = adev->mman.bdev.glob;
        struct amdgpu_vm_bo_base *bo_base;
 
+#if 0
        if (vm->bulk_moveable) {
                spin_lock(&glob->lru_lock);
                ttm_bo_bulk_move_lru_tail(&vm->lru_bulk_move);
                spin_unlock(&glob->lru_lock);
                return;
        }
+#endif
 
        memset(&vm->lru_bulk_move, 0, sizeof(vm->lru_bulk_move));
 
@@ -847,9 +849,6 @@ static void amdgpu_vm_bo_param(struct amdgpu_device *adev, struct amdgpu_vm *vm,
        bp->size = amdgpu_vm_bo_size(adev, level);
        bp->byte_align = AMDGPU_GPU_PAGE_SIZE;
        bp->domain = AMDGPU_GEM_DOMAIN_VRAM;
-       if (bp->size <= PAGE_SIZE && adev->asic_type >= CHIP_VEGA10 &&
-           adev->flags & AMD_IS_APU)
-               bp->domain |= AMDGPU_GEM_DOMAIN_GTT;
        bp->domain = amdgpu_bo_get_preferred_pin_domain(adev, bp->domain);
        bp->flags = AMDGPU_GEM_CREATE_VRAM_CONTIGUOUS |
                AMDGPU_GEM_CREATE_CPU_GTT_USWC;
@@ -3366,14 +3365,15 @@ void amdgpu_vm_get_task_info(struct amdgpu_device *adev, unsigned int pasid,
                         struct amdgpu_task_info *task_info)
 {
        struct amdgpu_vm *vm;
+       unsigned long flags;
 
-       spin_lock(&adev->vm_manager.pasid_lock);
+       spin_lock_irqsave(&adev->vm_manager.pasid_lock, flags);
 
        vm = idr_find(&adev->vm_manager.pasid_idr, pasid);
        if (vm)
                *task_info = vm->task_info;
 
-       spin_unlock(&adev->vm_manager.pasid_lock);
+       spin_unlock_irqrestore(&adev->vm_manager.pasid_lock, flags);
 }
 
 /**
index fdace00..e4cc1d4 100644 (file)
@@ -167,19 +167,6 @@ static void dce_virtual_crtc_disable(struct drm_crtc *crtc)
        struct amdgpu_crtc *amdgpu_crtc = to_amdgpu_crtc(crtc);
 
        dce_virtual_crtc_dpms(crtc, DRM_MODE_DPMS_OFF);
-       if (crtc->primary->fb) {
-               int r;
-               struct amdgpu_bo *abo;
-
-               abo = gem_to_amdgpu_bo(crtc->primary->fb->obj[0]);
-               r = amdgpu_bo_reserve(abo, true);
-               if (unlikely(r))
-                       DRM_ERROR("failed to reserve abo before unpin\n");
-               else {
-                       amdgpu_bo_unpin(abo);
-                       amdgpu_bo_unreserve(abo);
-               }
-       }
 
        amdgpu_crtc->pll_id = ATOM_PPLL_INVALID;
        amdgpu_crtc->encoder = NULL;
@@ -692,7 +679,9 @@ static int dce_virtual_pageflip(struct amdgpu_device *adev,
        spin_unlock_irqrestore(&adev->ddev->event_lock, flags);
 
        drm_crtc_vblank_put(&amdgpu_crtc->base);
-       schedule_work(&works->unpin_work);
+       amdgpu_bo_unref(&works->old_abo);
+       kfree(works->shared);
+       kfree(works);
 
        return 0;
 }
index 381f593..57cb3a5 100644 (file)
@@ -4233,7 +4233,6 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev)
        u32 tmp;
        u32 rb_bufsz;
        u64 rb_addr, rptr_addr, wptr_gpu_addr;
-       int r;
 
        /* Set the write pointer delay */
        WREG32(mmCP_RB_WPTR_DELAY, 0);
@@ -4278,9 +4277,8 @@ static int gfx_v8_0_cp_gfx_resume(struct amdgpu_device *adev)
        amdgpu_ring_clear_ring(ring);
        gfx_v8_0_cp_gfx_start(adev);
        ring->sched.ready = true;
-       r = amdgpu_ring_test_helper(ring);
 
-       return r;
+       return 0;
 }
 
 static void gfx_v8_0_cp_compute_enable(struct amdgpu_device *adev, bool enable)
@@ -4369,10 +4367,9 @@ static int gfx_v8_0_kiq_kcq_enable(struct amdgpu_device *adev)
                amdgpu_ring_write(kiq_ring, upper_32_bits(wptr_addr));
        }
 
-       r = amdgpu_ring_test_helper(kiq_ring);
-       if (r)
-               DRM_ERROR("KCQ enable failed\n");
-       return r;
+       amdgpu_ring_commit(kiq_ring);
+
+       return 0;
 }
 
 static int gfx_v8_0_deactivate_hqd(struct amdgpu_device *adev, u32 req)
@@ -4709,16 +4706,32 @@ static int gfx_v8_0_kcq_resume(struct amdgpu_device *adev)
        if (r)
                goto done;
 
-       /* Test KCQs - reversing the order of rings seems to fix ring test failure
-        * after GPU reset
-        */
-       for (i = adev->gfx.num_compute_rings - 1; i >= 0; i--) {
+done:
+       return r;
+}
+
+static int gfx_v8_0_cp_test_all_rings(struct amdgpu_device *adev)
+{
+       int r, i;
+       struct amdgpu_ring *ring;
+
+       /* collect all the ring_tests here, gfx, kiq, compute */
+       ring = &adev->gfx.gfx_ring[0];
+       r = amdgpu_ring_test_helper(ring);
+       if (r)
+               return r;
+
+       ring = &adev->gfx.kiq.ring;
+       r = amdgpu_ring_test_helper(ring);
+       if (r)
+               return r;
+
+       for (i = 0; i < adev->gfx.num_compute_rings; i++) {
                ring = &adev->gfx.compute_ring[i];
-               r = amdgpu_ring_test_helper(ring);
+               amdgpu_ring_test_helper(ring);
        }
 
-done:
-       return r;
+       return 0;
 }
 
 static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
@@ -4739,6 +4752,11 @@ static int gfx_v8_0_cp_resume(struct amdgpu_device *adev)
        r = gfx_v8_0_kcq_resume(adev);
        if (r)
                return r;
+
+       r = gfx_v8_0_cp_test_all_rings(adev);
+       if (r)
+               return r;
+
        gfx_v8_0_enable_gui_idle_interrupt(adev, true);
 
        return 0;
@@ -5086,6 +5104,8 @@ static int gfx_v8_0_post_soft_reset(void *handle)
            REG_GET_FIELD(grbm_soft_reset, GRBM_SOFT_RESET, SOFT_RESET_GFX))
                gfx_v8_0_cp_gfx_resume(adev);
 
+       gfx_v8_0_cp_test_all_rings(adev);
+
        adev->gfx.rlc.funcs->start(adev);
 
        return 0;
index 7556716..fbca049 100644 (file)
@@ -113,7 +113,10 @@ static const struct soc15_reg_golden golden_settings_gc_9_0[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_HI, 0xffffffff, 0x4a2c0e68),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTCP_CHAN_STEER_LO, 0xffffffff, 0xb5d3f197),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_CACHE_INVALIDATION, 0x3fff3af3, 0x19200000),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff)
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmVGT_GS_MAX_WAVE_ID, 0x00000fff, 0x000003ff),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800),
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000)
 };
 
 static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] =
@@ -135,10 +138,7 @@ static const struct soc15_reg_golden golden_settings_gc_9_0_vg10[] =
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmRMI_UTCL1_CNTL2, 0x00030000, 0x00020000),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmSPI_CONFIG_CNTL_1, 0x0000000f, 0x01000107),
        SOC15_REG_GOLDEN_VALUE(GC, 0, mmTD_CNTL, 0x00001800, 0x00000800),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC1_F32_INT_DIS, 0x00000000, 0x00000800),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_MEC2_F32_INT_DIS, 0x00000000, 0x00000800),
-       SOC15_REG_GOLDEN_VALUE(GC, 0, mmCP_DEBUG, 0x00000000, 0x00008000)
+       SOC15_REG_GOLDEN_VALUE(GC, 0, mmWD_UTCL1_CNTL, 0x08000000, 0x08000080)
 };
 
 static const struct soc15_reg_golden golden_settings_gc_9_0_vg20[] =
@@ -3587,6 +3587,8 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
 {
        uint32_t data, def;
 
+       amdgpu_gfx_rlc_enter_safe_mode(adev);
+
        /* It is disabled by HW by default */
        if (enable && (adev->cg_flags & AMD_CG_SUPPORT_GFX_MGCG)) {
                /* 1 - RLC_CGTT_MGCG_OVERRIDE */
@@ -3651,6 +3653,8 @@ static void gfx_v9_0_update_medium_grain_clock_gating(struct amdgpu_device *adev
                        WREG32_SOC15(GC, 0, mmCP_MEM_SLP_CNTL, data);
                }
        }
+
+       amdgpu_gfx_rlc_exit_safe_mode(adev);
 }
 
 static void gfx_v9_0_update_3d_clock_gating(struct amdgpu_device *adev,
index 8cbb465..b11a1c1 100644 (file)
@@ -174,7 +174,7 @@ static int xgpu_ai_send_access_requests(struct amdgpu_device *adev,
                        return r;
                }
                /* Retrieve checksum from mailbox2 */
-               if (req == IDH_REQ_GPU_INIT_ACCESS) {
+               if (req == IDH_REQ_GPU_INIT_ACCESS || req == IDH_REQ_GPU_RESET_ACCESS) {
                        adev->virt.fw_reserve.checksum_key =
                                RREG32_NO_KIQ(SOC15_REG_OFFSET(NBIO, 0,
                                        mmBIF_BX_PF0_MAILBOX_MSGBUF_RCV_DW2));
index 4cd31a2..186db18 100644 (file)
@@ -93,7 +93,20 @@ static void nbio_v7_4_enable_doorbell_aperture(struct amdgpu_device *adev,
 static void nbio_v7_4_enable_doorbell_selfring_aperture(struct amdgpu_device *adev,
                                                        bool enable)
 {
+       u32 tmp = 0;
 
+       if (enable) {
+               tmp = REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_EN, 1) |
+                     REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_MODE, 1) |
+                     REG_SET_FIELD(tmp, DOORBELL_SELFRING_GPA_APER_CNTL, DOORBELL_SELFRING_GPA_APER_SIZE, 0);
+
+               WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_BASE_LOW,
+                            lower_32_bits(adev->doorbell.base));
+               WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_BASE_HIGH,
+                            upper_32_bits(adev->doorbell.base));
+       }
+
+       WREG32_SOC15(NBIO, 0, mmDOORBELL_SELFRING_GPA_APER_CNTL, tmp);
 }
 
 static void nbio_v7_4_ih_doorbell_range(struct amdgpu_device *adev,
index 0c6e7f9..189fcb0 100644 (file)
@@ -152,18 +152,22 @@ static int psp_v11_0_init_microcode(struct psp_context *psp)
 
        snprintf(fw_name, sizeof(fw_name), "amdgpu/%s_ta.bin", chip_name);
        err = request_firmware(&adev->psp.ta_fw, fw_name, adev->dev);
-       if (err)
-               goto out2;
-
-       err = amdgpu_ucode_validate(adev->psp.ta_fw);
-       if (err)
-               goto out2;
-
-       ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
-       adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version);
-       adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes);
-       adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr +
-               le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
+       if (err) {
+               release_firmware(adev->psp.ta_fw);
+               adev->psp.ta_fw = NULL;
+               dev_info(adev->dev,
+                        "psp v11.0: Failed to load firmware \"%s\"\n", fw_name);
+       } else {
+               err = amdgpu_ucode_validate(adev->psp.ta_fw);
+               if (err)
+                       goto out2;
+
+               ta_hdr = (const struct ta_firmware_header_v1_0 *)adev->psp.ta_fw->data;
+               adev->psp.ta_xgmi_ucode_version = le32_to_cpu(ta_hdr->ta_xgmi_ucode_version);
+               adev->psp.ta_xgmi_ucode_size = le32_to_cpu(ta_hdr->ta_xgmi_size_bytes);
+               adev->psp.ta_xgmi_start_addr = (uint8_t *)ta_hdr +
+                       le32_to_cpu(ta_hdr->header.ucode_array_offset_bytes);
+       }
 
        return 0;
 
index fd0bfe1..aa2f71c 100644 (file)
@@ -78,7 +78,6 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = {
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_RLC1_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_PAGE, 0x000003ff, 0x000003c0),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_UTCL1_WATERMK, 0xfc000000, 0x00000000),
-       SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CLK_CTRL, 0xffffffff, 0x3f000100),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_IB_CNTL, 0x800f0100, 0x00000100),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GFX_RB_WPTR_POLL_CNTL, 0x0000fff0, 0x00403000),
@@ -96,6 +95,7 @@ static const struct soc15_reg_golden golden_settings_sdma_4[] = {
 static const struct soc15_reg_golden golden_settings_sdma_vg10[] = {
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002),
+       SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104002),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104002)
 };
@@ -103,6 +103,7 @@ static const struct soc15_reg_golden golden_settings_sdma_vg10[] = {
 static const struct soc15_reg_golden golden_settings_sdma_vg12[] = {
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001),
+       SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0018773f, 0x00104001),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0018773f, 0x00104001)
 };
@@ -127,7 +128,7 @@ static const struct soc15_reg_golden golden_settings_sdma0_4_2_init[] = {
 
 static const struct soc15_reg_golden golden_settings_sdma0_4_2[] =
 {
-       SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
+       SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_CLK_CTRL, 0xffffffff, 0x3f000100),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
        SOC15_REG_GOLDEN_VALUE(SDMA0, 0, mmSDMA0_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002),
@@ -157,7 +158,7 @@ static const struct soc15_reg_golden golden_settings_sdma0_4_2[] =
 };
 
 static const struct soc15_reg_golden golden_settings_sdma1_4_2[] = {
-       SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831d07),
+       SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CHICKEN_BITS, 0xfe931f07, 0x02831f07),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_CLK_CTRL, 0xffffffff, 0x3f000100),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG, 0x0000773f, 0x00004002),
        SOC15_REG_GOLDEN_VALUE(SDMA1, 0, mmSDMA1_GB_ADDR_CONFIG_READ, 0x0000773f, 0x00004002),
index 8849b74..9b63997 100644 (file)
@@ -729,11 +729,13 @@ static int soc15_common_early_init(void *handle)
        case CHIP_RAVEN:
                adev->asic_funcs = &soc15_asic_funcs;
                if (adev->rev_id >= 0x8)
-                       adev->external_rev_id = adev->rev_id + 0x81;
+                       adev->external_rev_id = adev->rev_id + 0x79;
                else if (adev->pdev->device == 0x15d8)
                        adev->external_rev_id = adev->rev_id + 0x41;
+               else if (adev->rev_id == 1)
+                       adev->external_rev_id = adev->rev_id + 0x20;
                else
-                       adev->external_rev_id = 0x1;
+                       adev->external_rev_id = adev->rev_id + 0x01;
 
                if (adev->rev_id >= 0x8) {
                        adev->cg_flags = AMD_CG_SUPPORT_GFX_MGCG |
index fbf0ee5..c361360 100644 (file)
@@ -4,8 +4,8 @@
 
 config HSA_AMD
        bool "HSA kernel driver for AMD GPU devices"
-       depends on DRM_AMDGPU && X86_64
-       imply AMD_IOMMU_V2
+       depends on DRM_AMDGPU && (X86_64 || ARM64)
+       imply AMD_IOMMU_V2 if X86_64
        select MMU_NOTIFIER
        help
          Enable this if you want to use HSA features on AMD GPU devices.
index b7bc7d7..2e7c449 100644 (file)
@@ -863,6 +863,7 @@ static int kfd_fill_mem_info_for_cpu(int numa_node_id, int *avail_size,
        return 0;
 }
 
+#ifdef CONFIG_X86_64
 static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size,
                                uint32_t *num_entries,
                                struct crat_subtype_iolink *sub_type_hdr)
@@ -905,6 +906,7 @@ static int kfd_fill_iolink_info_for_cpu(int numa_node_id, int *avail_size,
 
        return 0;
 }
+#endif
 
 /* kfd_create_vcrat_image_cpu - Create Virtual CRAT for CPU
  *
@@ -920,7 +922,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
        struct crat_subtype_generic *sub_type_hdr;
        int avail_size = *size;
        int numa_node_id;
+#ifdef CONFIG_X86_64
        uint32_t entries = 0;
+#endif
        int ret = 0;
 
        if (!pcrat_image || avail_size < VCRAT_SIZE_FOR_CPU)
@@ -982,6 +986,7 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
                        sub_type_hdr->length);
 
                /* Fill in Subtype: IO Link */
+#ifdef CONFIG_X86_64
                ret = kfd_fill_iolink_info_for_cpu(numa_node_id, &avail_size,
                                &entries,
                                (struct crat_subtype_iolink *)sub_type_hdr);
@@ -992,6 +997,9 @@ static int kfd_create_vcrat_image_cpu(void *pcrat_image, size_t *size)
 
                sub_type_hdr = (typeof(sub_type_hdr))((char *)sub_type_hdr +
                                sub_type_hdr->length * entries);
+#else
+               pr_info("IO link not available for non x86 platforms\n");
+#endif
 
                crat_table->num_domains++;
        }
index 5f5b2ac..09da916 100644 (file)
@@ -1093,8 +1093,6 @@ static uint32_t kfd_generate_gpu_id(struct kfd_dev *gpu)
  *             the GPU device is not already present in the topology device
  *             list then return NULL. This means a new topology device has to
  *             be created for this GPU.
- * TODO: Rather than assiging @gpu to first topology device withtout
- *             gpu attached, it will better to have more stringent check.
  */
 static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
 {
@@ -1102,12 +1100,20 @@ static struct kfd_topology_device *kfd_assign_gpu(struct kfd_dev *gpu)
        struct kfd_topology_device *out_dev = NULL;
 
        down_write(&topology_lock);
-       list_for_each_entry(dev, &topology_device_list, list)
+       list_for_each_entry(dev, &topology_device_list, list) {
+               /* Discrete GPUs need their own topology device list
+                * entries. Don't assign them to CPU/APU nodes.
+                */
+               if (!gpu->device_info->needs_iommu_device &&
+                   dev->node_props.cpu_cores_count)
+                       continue;
+
                if (!dev->gpu && (dev->node_props.simd_count > 0)) {
                        dev->gpu = gpu;
                        out_dev = dev;
                        break;
                }
+       }
        up_write(&topology_lock);
        return out_dev;
 }
@@ -1392,7 +1398,6 @@ int kfd_topology_enum_kfd_devices(uint8_t idx, struct kfd_dev **kdev)
 
 static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask)
 {
-       const struct cpuinfo_x86 *cpuinfo;
        int first_cpu_of_numa_node;
 
        if (!cpumask || cpumask == cpu_none_mask)
@@ -1400,9 +1405,11 @@ static int kfd_cpumask_to_apic_id(const struct cpumask *cpumask)
        first_cpu_of_numa_node = cpumask_first(cpumask);
        if (first_cpu_of_numa_node >= nr_cpu_ids)
                return -1;
-       cpuinfo = &cpu_data(first_cpu_of_numa_node);
-
-       return cpuinfo->apicid;
+#ifdef CONFIG_X86_64
+       return cpu_data(first_cpu_of_numa_node).apicid;
+#else
+       return first_cpu_of_numa_node;
+#endif
 }
 
 /* kfd_numa_node_to_apic_id - Returns the APIC ID of the first logical processor
index a9a28db..5296b8f 100644 (file)
@@ -699,22 +699,36 @@ static void s3_handle_mst(struct drm_device *dev, bool suspend)
 {
        struct amdgpu_dm_connector *aconnector;
        struct drm_connector *connector;
+       struct drm_dp_mst_topology_mgr *mgr;
+       int ret;
+       bool need_hotplug = false;
 
        drm_modeset_lock(&dev->mode_config.connection_mutex, NULL);
 
-       list_for_each_entry(connector, &dev->mode_config.connector_list, head) {
-                  aconnector = to_amdgpu_dm_connector(connector);
-                  if (aconnector->dc_link->type == dc_connection_mst_branch &&
-                                  !aconnector->mst_port) {
+       list_for_each_entry(connector, &dev->mode_config.connector_list,
+                           head) {
+               aconnector = to_amdgpu_dm_connector(connector);
+               if (aconnector->dc_link->type != dc_connection_mst_branch ||
+                   aconnector->mst_port)
+                       continue;
+
+               mgr = &aconnector->mst_mgr;
 
-                          if (suspend)
-                                  drm_dp_mst_topology_mgr_suspend(&aconnector->mst_mgr);
-                          else
-                                  drm_dp_mst_topology_mgr_resume(&aconnector->mst_mgr);
-                  }
+               if (suspend) {
+                       drm_dp_mst_topology_mgr_suspend(mgr);
+               } else {
+                       ret = drm_dp_mst_topology_mgr_resume(mgr);
+                       if (ret < 0) {
+                               drm_dp_mst_topology_mgr_set_mst(mgr, false);
+                               need_hotplug = true;
+                       }
+               }
        }
 
        drm_modeset_unlock(&dev->mode_config.connection_mutex);
+
+       if (need_hotplug)
+               drm_kms_helper_hotplug_event(dev);
 }
 
 /**
@@ -772,12 +786,13 @@ static int dm_suspend(void *handle)
        struct amdgpu_display_manager *dm = &adev->dm;
        int ret = 0;
 
+       WARN_ON(adev->dm.cached_state);
+       adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev);
+
        s3_handle_mst(adev->ddev, true);
 
        amdgpu_dm_irq_suspend(adev);
 
-       WARN_ON(adev->dm.cached_state);
-       adev->dm.cached_state = drm_atomic_helper_suspend(adev->ddev);
 
        dc_set_power_state(dm->dc, DC_ACPI_CM_POWER_STATE_D3);
 
@@ -898,7 +913,6 @@ static int dm_resume(void *handle)
        struct drm_plane_state *new_plane_state;
        struct dm_plane_state *dm_new_plane_state;
        enum dc_connection_type new_connection_type = dc_connection_none;
-       int ret;
        int i;
 
        /* power on hardware */
@@ -971,13 +985,13 @@ static int dm_resume(void *handle)
                }
        }
 
-       ret = drm_atomic_helper_resume(ddev, dm->cached_state);
+       drm_atomic_helper_resume(ddev, dm->cached_state);
 
        dm->cached_state = NULL;
 
        amdgpu_dm_irq_resume_late(adev);
 
-       return ret;
+       return 0;
 }
 
 /**
@@ -1759,7 +1773,7 @@ static int amdgpu_dm_backlight_update_status(struct backlight_device *bd)
                + caps.min_input_signal * 0x101;
 
        if (dc_link_set_backlight_level(dm->backlight_link,
-                       brightness, 0, 0))
+                       brightness, 0))
                return 0;
        else
                return 1;
@@ -4069,7 +4083,8 @@ void amdgpu_dm_connector_init_helper(struct amdgpu_display_manager *dm,
        }
 
        if (connector_type == DRM_MODE_CONNECTOR_HDMIA ||
-           connector_type == DRM_MODE_CONNECTOR_DisplayPort) {
+           connector_type == DRM_MODE_CONNECTOR_DisplayPort ||
+           connector_type == DRM_MODE_CONNECTOR_eDP) {
                drm_connector_attach_vrr_capable_property(
                        &aconnector->base);
        }
@@ -5920,7 +5935,7 @@ static int amdgpu_dm_atomic_check(struct drm_device *dev,
        for_each_oldnew_crtc_in_state(state, crtc, old_crtc_state, new_crtc_state, i) {
                if (!drm_atomic_crtc_needs_modeset(new_crtc_state) &&
                    !new_crtc_state->color_mgmt_changed &&
-                   !new_crtc_state->vrr_enabled)
+                   old_crtc_state->vrr_enabled == new_crtc_state->vrr_enabled)
                        continue;
 
                if (!new_crtc_state->enable)
index 9a7ac58..ddd75a4 100644 (file)
@@ -671,6 +671,25 @@ static ssize_t dp_phy_test_pattern_debugfs_write(struct file *f, const char __us
        return bytes_from_user;
 }
 
+/*
+ * Returns the min and max vrr vfreq through the connector's debugfs file.
+ * Example usage: cat /sys/kernel/debug/dri/0/DP-1/vrr_range
+ */
+static int vrr_range_show(struct seq_file *m, void *data)
+{
+       struct drm_connector *connector = m->private;
+       struct amdgpu_dm_connector *aconnector = to_amdgpu_dm_connector(connector);
+
+       if (connector->status != connector_status_connected)
+               return -ENODEV;
+
+       seq_printf(m, "Min: %u\n", (unsigned int)aconnector->min_vfreq);
+       seq_printf(m, "Max: %u\n", (unsigned int)aconnector->max_vfreq);
+
+       return 0;
+}
+DEFINE_SHOW_ATTRIBUTE(vrr_range);
+
 static const struct file_operations dp_link_settings_debugfs_fops = {
        .owner = THIS_MODULE,
        .read = dp_link_settings_read,
@@ -697,7 +716,8 @@ static const struct {
 } dp_debugfs_entries[] = {
                {"link_settings", &dp_link_settings_debugfs_fops},
                {"phy_settings", &dp_phy_settings_debugfs_fop},
-               {"test_pattern", &dp_phy_test_pattern_fops}
+               {"test_pattern", &dp_phy_test_pattern_fops},
+               {"vrr_range", &vrr_range_fops}
 };
 
 int connector_debugfs_init(struct amdgpu_dm_connector *connector)
index 52deacf..b0265db 100644 (file)
@@ -2190,8 +2190,7 @@ int dc_link_get_backlight_level(const struct dc_link *link)
 
 bool dc_link_set_backlight_level(const struct dc_link *link,
                uint32_t backlight_pwm_u16_16,
-               uint32_t frame_ramp,
-               const struct dc_stream_state *stream)
+               uint32_t frame_ramp)
 {
        struct dc  *core_dc = link->ctx->dc;
        struct abm *abm = core_dc->res_pool->abm;
@@ -2206,10 +2205,6 @@ bool dc_link_set_backlight_level(const struct dc_link *link,
                (abm->funcs->set_backlight_level_pwm == NULL))
                return false;
 
-       if (stream)
-               ((struct dc_stream_state *)stream)->bl_pwm_level =
-                               backlight_pwm_u16_16;
-
        use_smooth_brightness = dmcu->funcs->is_dmcu_initialized(dmcu);
 
        DC_LOG_BACKLIGHT("New Backlight level: %d (0x%X)\n",
@@ -2637,11 +2632,6 @@ void core_link_enable_stream(
 
                if (dc_is_dp_signal(pipe_ctx->stream->signal))
                        enable_stream_features(pipe_ctx);
-
-               dc_link_set_backlight_level(pipe_ctx->stream->sink->link,
-                               pipe_ctx->stream->bl_pwm_level,
-                               0,
-                               pipe_ctx->stream);
        }
 
 }
index 29f19d5..b2243e0 100644 (file)
@@ -146,8 +146,7 @@ static inline struct dc_link *dc_get_link_at_index(struct dc *dc, uint32_t link_
  */
 bool dc_link_set_backlight_level(const struct dc_link *dc_link,
                uint32_t backlight_pwm_u16_16,
-               uint32_t frame_ramp,
-               const struct dc_stream_state *stream);
+               uint32_t frame_ramp);
 
 int dc_link_get_backlight_level(const struct dc_link *dc_link);
 
index be34d63..d70c9e1 100644 (file)
@@ -91,7 +91,6 @@ struct dc_stream_state {
 
        /* DMCU info */
        unsigned int abm_level;
-       unsigned int bl_pwm_level;
 
        /* from core_stream struct */
        struct dc_context *ctx;
index afd287f..7a72ee4 100644 (file)
@@ -591,7 +591,15 @@ static void dce11_pplib_apply_display_requirements(
                        dc,
                        context->bw.dce.sclk_khz);
 
-       pp_display_cfg->min_dcfclock_khz = pp_display_cfg->min_engine_clock_khz;
+       /*
+        * As workaround for >4x4K lightup set dcfclock to min_engine_clock value.
+        * This is not required for less than 5 displays,
+        * thus don't request decfclk in dc to avoid impact
+        * on power saving.
+        *
+        */
+       pp_display_cfg->min_dcfclock_khz = (context->stream_count > 4)?
+                       pp_display_cfg->min_engine_clock_khz : 0;
 
        pp_display_cfg->min_engine_clock_deep_sleep_khz
                        = context->bw.dce.sclk_deep_sleep_khz;
@@ -654,6 +662,11 @@ static void dce11_update_clocks(struct clk_mgr *clk_mgr,
 {
        struct dce_clk_mgr *clk_mgr_dce = TO_DCE_CLK_MGR(clk_mgr);
        struct dm_pp_power_level_change_request level_change_req;
+       int patched_disp_clk = context->bw.dce.dispclk_khz;
+
+       /*TODO: W/A for dal3 linux, investigate why this works */
+       if (!clk_mgr_dce->dfs_bypass_active)
+               patched_disp_clk = patched_disp_clk * 115 / 100;
 
        level_change_req.power_level = dce_get_required_clocks_state(clk_mgr, context);
        /* get max clock state from PPLIB */
@@ -663,9 +676,9 @@ static void dce11_update_clocks(struct clk_mgr *clk_mgr,
                        clk_mgr_dce->cur_min_clks_state = level_change_req.power_level;
        }
 
-       if (should_set_clock(safe_to_lower, context->bw.dce.dispclk_khz, clk_mgr->clks.dispclk_khz)) {
-               context->bw.dce.dispclk_khz = dce_set_clock(clk_mgr, context->bw.dce.dispclk_khz);
-               clk_mgr->clks.dispclk_khz = context->bw.dce.dispclk_khz;
+       if (should_set_clock(safe_to_lower, patched_disp_clk, clk_mgr->clks.dispclk_khz)) {
+               context->bw.dce.dispclk_khz = dce_set_clock(clk_mgr, patched_disp_clk);
+               clk_mgr->clks.dispclk_khz = patched_disp_clk;
        }
        dce11_pplib_apply_display_requirements(clk_mgr->ctx->dc, context);
 }
index acd4185..a6b80fd 100644 (file)
@@ -37,6 +37,10 @@ void dce100_prepare_bandwidth(
                struct dc *dc,
                struct dc_state *context);
 
+void dce100_optimize_bandwidth(
+               struct dc *dc,
+               struct dc_state *context);
+
 bool dce100_enable_display_power_gating(struct dc *dc, uint8_t controller_id,
                                        struct dc_bios *dcb,
                                        enum pipe_gating_control power_gating);
index 4bf2475..8f09b86 100644 (file)
@@ -1000,7 +1000,7 @@ void dce110_enable_audio_stream(struct pipe_ctx *pipe_ctx)
 
                pipe_ctx->stream_res.audio->funcs->az_enable(pipe_ctx->stream_res.audio);
 
-               if (num_audio == 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
+               if (num_audio >= 1 && pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
                        /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
                        pp_smu->set_pme_wa_enable(&pp_smu->pp_smu);
                /* un-mute audio */
@@ -1017,6 +1017,8 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
        pipe_ctx->stream_res.stream_enc->funcs->audio_mute_control(
                        pipe_ctx->stream_res.stream_enc, true);
        if (pipe_ctx->stream_res.audio) {
+               struct pp_smu_funcs_rv *pp_smu = dc->res_pool->pp_smu;
+
                if (option != KEEP_ACQUIRED_RESOURCE ||
                                !dc->debug.az_endpoint_mute_only) {
                        /*only disalbe az_endpoint if power down or free*/
@@ -1036,6 +1038,9 @@ void dce110_disable_audio_stream(struct pipe_ctx *pipe_ctx, int option)
                        update_audio_usage(&dc->current_state->res_ctx, dc->res_pool, pipe_ctx->stream_res.audio, false);
                        pipe_ctx->stream_res.audio = NULL;
                }
+               if (pp_smu != NULL && pp_smu->set_pme_wa_enable != NULL)
+                       /*this is the first audio. apply the PME w/a in order to wake AZ from D3*/
+                       pp_smu->set_pme_wa_enable(&pp_smu->pp_smu);
 
                /* TODO: notify audio driver for if audio modes list changed
                 * add audio mode list change flag */
index a60a90e..c454317 100644 (file)
@@ -77,6 +77,6 @@ void dce80_hw_sequencer_construct(struct dc *dc)
        dc->hwss.enable_display_power_gating = dce100_enable_display_power_gating;
        dc->hwss.pipe_control_lock = dce_pipe_control_lock;
        dc->hwss.prepare_bandwidth = dce100_prepare_bandwidth;
-       dc->hwss.optimize_bandwidth = dce100_prepare_bandwidth;
+       dc->hwss.optimize_bandwidth = dce100_optimize_bandwidth;
 }
 
index cdd1d6b..4e9ea50 100644 (file)
@@ -790,9 +790,22 @@ bool dce80_validate_bandwidth(
        struct dc *dc,
        struct dc_state *context)
 {
-       /* TODO implement when needed but for now hardcode max value*/
-       context->bw.dce.dispclk_khz = 681000;
-       context->bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER_CZ;
+       int i;
+       bool at_least_one_pipe = false;
+
+       for (i = 0; i < dc->res_pool->pipe_count; i++) {
+               if (context->res_ctx.pipe_ctx[i].stream)
+                       at_least_one_pipe = true;
+       }
+
+       if (at_least_one_pipe) {
+               /* TODO implement when needed but for now hardcode max value*/
+               context->bw.dce.dispclk_khz = 681000;
+               context->bw.dce.yclk_khz = 250000 * MEMORY_TYPE_MULTIPLIER_CZ;
+       } else {
+               context->bw.dce.dispclk_khz = 0;
+               context->bw.dce.yclk_khz = 0;
+       }
 
        return true;
 }
index dcb3c55..cd1ebe5 100644 (file)
@@ -463,7 +463,7 @@ void dpp1_set_cursor_position(
        if (src_y_offset >= (int)param->viewport.height)
                cur_en = 0;  /* not visible beyond bottom edge*/
 
-       if (src_y_offset < 0)
+       if (src_y_offset + (int)height <= 0)
                cur_en = 0;  /* not visible beyond top edge*/
 
        REG_UPDATE(CURSOR0_CONTROL,
index 345af01..d1acd71 100644 (file)
@@ -1140,7 +1140,7 @@ void hubp1_cursor_set_position(
        if (src_y_offset >= (int)param->viewport.height)
                cur_en = 0;  /* not visible beyond bottom edge*/
 
-       if (src_y_offset < 0) //+ (int)hubp->curs_attr.height
+       if (src_y_offset + (int)hubp->curs_attr.height <= 0)
                cur_en = 0;  /* not visible beyond top edge*/
 
        if (cur_en && REG_READ(CURSOR_SURFACE_ADDRESS) == 0)
index 91e015e..41883c9 100644 (file)
@@ -2355,29 +2355,22 @@ static void dcn10_apply_ctx_for_surface(
                        top_pipe_to_program->plane_state->update_flags.bits.full_update)
                for (i = 0; i < dc->res_pool->pipe_count; i++) {
                        struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
-
+                       tg = pipe_ctx->stream_res.tg;
                        /* Skip inactive pipes and ones already updated */
                        if (!pipe_ctx->stream || pipe_ctx->stream == stream
-                                       || !pipe_ctx->plane_state)
+                                       || !pipe_ctx->plane_state
+                                       || !tg->funcs->is_tg_enabled(tg))
                                continue;
 
-                       pipe_ctx->stream_res.tg->funcs->lock(pipe_ctx->stream_res.tg);
+                       tg->funcs->lock(tg);
 
                        pipe_ctx->plane_res.hubp->funcs->hubp_setup_interdependent(
                                pipe_ctx->plane_res.hubp,
                                &pipe_ctx->dlg_regs,
                                &pipe_ctx->ttu_regs);
-               }
-
-       for (i = 0; i < dc->res_pool->pipe_count; i++) {
-               struct pipe_ctx *pipe_ctx = &context->res_ctx.pipe_ctx[i];
 
-               if (!pipe_ctx->stream || pipe_ctx->stream == stream
-                               || !pipe_ctx->plane_state)
-                       continue;
-
-               dcn10_pipe_control_lock(dc, pipe_ctx, false);
-       }
+                       tg->funcs->unlock(tg);
+               }
 
        if (num_planes == 0)
                false_optc_underflow_wa(dc, stream, tg);
@@ -2665,8 +2658,8 @@ static void dcn10_set_cursor_position(struct pipe_ctx *pipe_ctx)
                .mirror = pipe_ctx->plane_state->horizontal_mirror
        };
 
-       pos_cpy.x -= pipe_ctx->plane_state->dst_rect.x;
-       pos_cpy.y -= pipe_ctx->plane_state->dst_rect.y;
+       pos_cpy.x_hotspot += pipe_ctx->plane_state->dst_rect.x;
+       pos_cpy.y_hotspot += pipe_ctx->plane_state->dst_rect.y;
 
        if (pipe_ctx->plane_state->address.type
                        == PLN_ADDR_TYPE_VIDEO_PROGRESSIVE)
index 00f63b7..c11a443 100644 (file)
@@ -57,6 +57,7 @@ static const unsigned char abm_config[abm_defines_max_config][abm_defines_max_le
 #define NUM_POWER_FN_SEGS 8
 #define NUM_BL_CURVE_SEGS 16
 
+#pragma pack(push, 1)
 /* NOTE: iRAM is 256B in size */
 struct iram_table_v_2 {
        /* flags                      */
@@ -100,6 +101,7 @@ struct iram_table_v_2 {
        uint8_t dummy8;                                                 /* 0xfe       */
        uint8_t dummy9;                                                 /* 0xff       */
 };
+#pragma pack(pop)
 
 static uint16_t backlight_8_to_16(unsigned int backlight_8bit)
 {
index 1479ea1..789c4f2 100644 (file)
@@ -127,12 +127,13 @@ enum amd_pp_task {
 };
 
 enum PP_SMC_POWER_PROFILE {
-       PP_SMC_POWER_PROFILE_FULLSCREEN3D = 0x0,
-       PP_SMC_POWER_PROFILE_POWERSAVING  = 0x1,
-       PP_SMC_POWER_PROFILE_VIDEO        = 0x2,
-       PP_SMC_POWER_PROFILE_VR           = 0x3,
-       PP_SMC_POWER_PROFILE_COMPUTE      = 0x4,
-       PP_SMC_POWER_PROFILE_CUSTOM       = 0x5,
+       PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT = 0x0,
+       PP_SMC_POWER_PROFILE_FULLSCREEN3D = 0x1,
+       PP_SMC_POWER_PROFILE_POWERSAVING  = 0x2,
+       PP_SMC_POWER_PROFILE_VIDEO        = 0x3,
+       PP_SMC_POWER_PROFILE_VR           = 0x4,
+       PP_SMC_POWER_PROFILE_COMPUTE      = 0x5,
+       PP_SMC_POWER_PROFILE_CUSTOM       = 0x6,
 };
 
 enum {
index 0173d04..310b102 100644 (file)
@@ -64,17 +64,19 @@ static int ci_set_asic_special_caps(struct pp_hwmgr *hwmgr);
 
 static void hwmgr_init_workload_prority(struct pp_hwmgr *hwmgr)
 {
-       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 2;
-       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 0;
-       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 1;
-       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 3;
-       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 4;
-
-       hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_POWERSAVING;
-       hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_VIDEO;
-       hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
-       hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VR;
-       hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_COMPUTE;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT] = 0;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_FULLSCREEN3D] = 1;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_POWERSAVING] = 2;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO] = 3;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VR] = 4;
+       hwmgr->workload_prority[PP_SMC_POWER_PROFILE_COMPUTE] = 5;
+
+       hwmgr->workload_setting[0] = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+       hwmgr->workload_setting[1] = PP_SMC_POWER_PROFILE_FULLSCREEN3D;
+       hwmgr->workload_setting[2] = PP_SMC_POWER_PROFILE_POWERSAVING;
+       hwmgr->workload_setting[3] = PP_SMC_POWER_PROFILE_VIDEO;
+       hwmgr->workload_setting[4] = PP_SMC_POWER_PROFILE_VR;
+       hwmgr->workload_setting[5] = PP_SMC_POWER_PROFILE_COMPUTE;
 }
 
 int hwmgr_early_init(struct pp_hwmgr *hwmgr)
index f95c5f5..5273de3 100644 (file)
@@ -1033,6 +1033,7 @@ static int smu10_get_clock_by_type_with_latency(struct pp_hwmgr *hwmgr,
                break;
        case amd_pp_dpp_clock:
                pclk_vol_table = pinfo->vdd_dep_on_dppclk;
+               break;
        default:
                return -EINVAL;
        }
index d913904..c8f5c00 100644 (file)
@@ -77,8 +77,9 @@
 #define PCIE_BUS_CLK                10000
 #define TCLK                        (PCIE_BUS_CLK / 10)
 
-static const struct profile_mode_setting smu7_profiling[6] =
-                                       {{1, 0, 100, 30, 1, 0, 100, 10},
+static const struct profile_mode_setting smu7_profiling[7] =
+                                       {{0, 0, 0, 0, 0, 0, 0, 0},
+                                        {1, 0, 100, 30, 1, 0, 100, 10},
                                         {1, 10, 0, 30, 0, 0, 0, 0},
                                         {0, 0, 0, 0, 1, 10, 16, 31},
                                         {1, 0, 11, 50, 1, 0, 100, 10},
@@ -4889,7 +4890,8 @@ static int smu7_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
        uint32_t i, size = 0;
        uint32_t len;
 
-       static const char *profile_name[6] = {"3D_FULL_SCREEN",
+       static const char *profile_name[7] = {"BOOTUP_DEFAULT",
+                                       "3D_FULL_SCREEN",
                                        "POWER_SAVING",
                                        "VIDEO",
                                        "VR",
index 79c8624..91e3bbe 100644 (file)
@@ -804,9 +804,9 @@ static int vega10_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 
        hwmgr->backend = data;
 
-       hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO];
-       hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
-       hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
+       hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
+       hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+       hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
 
        vega10_set_default_registry_data(hwmgr);
        data->disable_dpm_mask = 0xff;
@@ -4668,13 +4668,15 @@ static int vega10_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
 {
        struct vega10_hwmgr *data = hwmgr->backend;
        uint32_t i, size = 0;
-       static const uint8_t profile_mode_setting[5][4] = {{70, 60, 1, 3,},
+       static const uint8_t profile_mode_setting[6][4] = {{70, 60, 0, 0,},
+                                               {70, 60, 1, 3,},
                                                {90, 60, 0, 0,},
                                                {70, 60, 0, 0,},
                                                {70, 90, 0, 0,},
                                                {30, 60, 0, 6,},
                                                };
-       static const char *profile_name[6] = {"3D_FULL_SCREEN",
+       static const char *profile_name[7] = {"BOOTUP_DEFAULT",
+                                       "3D_FULL_SCREEN",
                                        "POWER_SAVING",
                                        "VIDEO",
                                        "VR",
index b8747a5..99d596d 100644 (file)
@@ -32,6 +32,7 @@
 #include "vega10_pptable.h"
 
 #define NUM_DSPCLK_LEVELS 8
+#define VEGA10_ENGINECLOCK_HARDMAX 198000
 
 static void set_hw_cap(struct pp_hwmgr *hwmgr, bool enable,
                enum phm_platform_caps cap)
@@ -258,7 +259,26 @@ static int init_over_drive_limits(
                struct pp_hwmgr *hwmgr,
                const ATOM_Vega10_POWERPLAYTABLE *powerplay_table)
 {
-       hwmgr->platform_descriptor.overdriveLimit.engineClock =
+       const ATOM_Vega10_GFXCLK_Dependency_Table *gfxclk_dep_table =
+                       (const ATOM_Vega10_GFXCLK_Dependency_Table *)
+                       (((unsigned long) powerplay_table) +
+                       le16_to_cpu(powerplay_table->usGfxclkDependencyTableOffset));
+       bool is_acg_enabled = false;
+       ATOM_Vega10_GFXCLK_Dependency_Record_V2 *patom_record_v2;
+
+       if (gfxclk_dep_table->ucRevId == 1) {
+               patom_record_v2 =
+                       (ATOM_Vega10_GFXCLK_Dependency_Record_V2 *)gfxclk_dep_table->entries;
+               is_acg_enabled =
+                       (bool)patom_record_v2[gfxclk_dep_table->ucNumEntries-1].ucACGEnable;
+       }
+
+       if (powerplay_table->ulMaxODEngineClock > VEGA10_ENGINECLOCK_HARDMAX &&
+               !is_acg_enabled)
+               hwmgr->platform_descriptor.overdriveLimit.engineClock =
+                       VEGA10_ENGINECLOCK_HARDMAX;
+       else
+               hwmgr->platform_descriptor.overdriveLimit.engineClock =
                        le32_to_cpu(powerplay_table->ulMaxODEngineClock);
        hwmgr->platform_descriptor.overdriveLimit.memoryClock =
                        le32_to_cpu(powerplay_table->ulMaxODMemoryClock);
index 5436444..0c82129 100644 (file)
@@ -753,6 +753,22 @@ static int vega12_init_smc_table(struct pp_hwmgr *hwmgr)
        return 0;
 }
 
+static int vega12_run_acg_btc(struct pp_hwmgr *hwmgr)
+{
+       uint32_t result;
+
+       PP_ASSERT_WITH_CODE(
+               smum_send_msg_to_smc(hwmgr, PPSMC_MSG_RunAcgBtc) == 0,
+               "[Run_ACG_BTC] Attempt to run ACG BTC failed!",
+               return -EINVAL);
+
+       result = smum_get_argument(hwmgr);
+       PP_ASSERT_WITH_CODE(result == 1,
+                       "Failed to run ACG BTC!", return -EINVAL);
+
+       return 0;
+}
+
 static int vega12_set_allowed_featuresmask(struct pp_hwmgr *hwmgr)
 {
        struct vega12_hwmgr *data =
@@ -931,6 +947,11 @@ static int vega12_enable_dpm_tasks(struct pp_hwmgr *hwmgr)
                        "Failed to initialize SMC table!",
                        result = tmp_result);
 
+       tmp_result = vega12_run_acg_btc(hwmgr);
+       PP_ASSERT_WITH_CODE(!tmp_result,
+                       "Failed to run ACG BTC!",
+                       result = tmp_result);
+
        result = vega12_enable_all_smu_features(hwmgr);
        PP_ASSERT_WITH_CODE(!result,
                        "Failed to enable all smu features!",
index 26154f9..82935a3 100644 (file)
@@ -390,9 +390,9 @@ static int vega20_hwmgr_backend_init(struct pp_hwmgr *hwmgr)
 
        hwmgr->backend = data;
 
-       hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_VIDEO];
-       hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
-       hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_VIDEO;
+       hwmgr->workload_mask = 1 << hwmgr->workload_prority[PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT];
+       hwmgr->power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
+       hwmgr->default_power_profile_mode = PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT;
 
        vega20_set_default_registry_data(hwmgr);
 
@@ -980,6 +980,9 @@ static int vega20_od8_set_feature_capabilities(
            pp_table->FanZeroRpmEnable)
                od_settings->overdrive8_capabilities |= OD8_FAN_ZERO_RPM_CONTROL;
 
+       if (!od_settings->overdrive8_capabilities)
+               hwmgr->od_enabled = false;
+
        return 0;
 }
 
@@ -1689,13 +1692,6 @@ static int vega20_upload_dpm_min_level(struct pp_hwmgr *hwmgr, uint32_t feature_
                                        (PPCLK_UCLK << 16) | (min_freq & 0xffff))),
                                        "Failed to set soft min memclk !",
                                        return ret);
-
-               min_freq = data->dpm_table.mem_table.dpm_state.hard_min_level;
-               PP_ASSERT_WITH_CODE(!(ret = smum_send_msg_to_smc_with_parameter(
-                                       hwmgr, PPSMC_MSG_SetHardMinByFreq,
-                                       (PPCLK_UCLK << 16) | (min_freq & 0xffff))),
-                                       "Failed to set hard min memclk !",
-                                       return ret);
        }
 
        if (data->smu_features[GNLD_DPM_UVD].enabled &&
@@ -2248,6 +2244,13 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
                soft_min_level = mask ? (ffs(mask) - 1) : 0;
                soft_max_level = mask ? (fls(mask) - 1) : 0;
 
+               if (soft_max_level >= data->dpm_table.gfx_table.count) {
+                       pr_err("Clock level specified %d is over max allowed %d\n",
+                                       soft_max_level,
+                                       data->dpm_table.gfx_table.count - 1);
+                       return -EINVAL;
+               }
+
                data->dpm_table.gfx_table.dpm_state.soft_min_level =
                        data->dpm_table.gfx_table.dpm_levels[soft_min_level].value;
                data->dpm_table.gfx_table.dpm_state.soft_max_level =
@@ -2268,6 +2271,13 @@ static int vega20_force_clock_level(struct pp_hwmgr *hwmgr,
                soft_min_level = mask ? (ffs(mask) - 1) : 0;
                soft_max_level = mask ? (fls(mask) - 1) : 0;
 
+               if (soft_max_level >= data->dpm_table.mem_table.count) {
+                       pr_err("Clock level specified %d is over max allowed %d\n",
+                                       soft_max_level,
+                                       data->dpm_table.mem_table.count - 1);
+                       return -EINVAL;
+               }
+
                data->dpm_table.mem_table.dpm_state.soft_min_level =
                        data->dpm_table.mem_table.dpm_levels[soft_min_level].value;
                data->dpm_table.mem_table.dpm_state.soft_max_level =
@@ -3261,6 +3271,9 @@ static int conv_power_profile_to_pplib_workload(int power_profile)
        int pplib_workload = 0;
 
        switch (power_profile) {
+       case PP_SMC_POWER_PROFILE_BOOTUP_DEFAULT:
+               pplib_workload = WORKLOAD_DEFAULT_BIT;
+               break;
        case PP_SMC_POWER_PROFILE_FULLSCREEN3D:
                pplib_workload = WORKLOAD_PPLIB_FULL_SCREEN_3D_BIT;
                break;
@@ -3290,6 +3303,7 @@ static int vega20_get_power_profile_mode(struct pp_hwmgr *hwmgr, char *buf)
        uint32_t i, size = 0;
        uint16_t workload_type = 0;
        static const char *profile_name[] = {
+                                       "BOOTUP_DEFAULT",
                                        "3D_FULL_SCREEN",
                                        "POWER_SAVING",
                                        "VIDEO",
index 0d298a0..8cb831b 100644 (file)
@@ -705,7 +705,7 @@ enum PP_TABLE_VERSION {
 /**
  * The main hardware manager structure.
  */
-#define Workload_Policy_Max 5
+#define Workload_Policy_Max 6
 
 struct pp_hwmgr {
        void *adev;
index 8e28e73..e6403b9 100644 (file)
@@ -98,6 +98,8 @@
 #define DP0_STARTVAL           0x064c
 #define DP0_ACTIVEVAL          0x0650
 #define DP0_SYNCVAL            0x0654
+#define SYNCVAL_HS_POL_ACTIVE_LOW      (1 << 15)
+#define SYNCVAL_VS_POL_ACTIVE_LOW      (1 << 31)
 #define DP0_MISC               0x0658
 #define TU_SIZE_RECOMMENDED            (63) /* LSCLK cycles per TU */
 #define BPC_6                          (0 << 5)
 #define DP0_LTLOOPCTRL         0x06d8
 #define DP0_SNKLTCTRL          0x06e4
 
+#define DP1_SRCCTRL            0x07a0
+
 /* PHY */
 #define DP_PHY_CTRL            0x0800
 #define DP_PHY_RST                     BIT(28)  /* DP PHY Global Soft Reset */
 #define PHY_M1_RST                     BIT(12)  /* Reset PHY1 Main Channel */
 #define PHY_RDY                                BIT(16)  /* PHY Main Channels Ready */
 #define PHY_M0_RST                     BIT(8)   /* Reset PHY0 Main Channel */
+#define PHY_2LANE                      BIT(2)   /* PHY Enable 2 lanes */
 #define PHY_A0_EN                      BIT(1)   /* PHY Aux Channel0 Enable */
 #define PHY_M0_EN                      BIT(0)   /* PHY Main Channel0 Enable */
 
@@ -540,6 +545,7 @@ static int tc_aux_link_setup(struct tc_data *tc)
        unsigned long rate;
        u32 value;
        int ret;
+       u32 dp_phy_ctrl;
 
        rate = clk_get_rate(tc->refclk);
        switch (rate) {
@@ -564,7 +570,10 @@ static int tc_aux_link_setup(struct tc_data *tc)
        value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
        tc_write(SYS_PLLPARAM, value);
 
-       tc_write(DP_PHY_CTRL, BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN);
+       dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN;
+       if (tc->link.base.num_lanes == 2)
+               dp_phy_ctrl |= PHY_2LANE;
+       tc_write(DP_PHY_CTRL, dp_phy_ctrl);
 
        /*
         * Initially PLLs are in bypass. Force PLL parameter update,
@@ -719,7 +728,9 @@ static int tc_set_video_mode(struct tc_data *tc, struct drm_display_mode *mode)
 
        tc_write(DP0_ACTIVEVAL, (mode->vdisplay << 16) | (mode->hdisplay));
 
-       tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0));
+       tc_write(DP0_SYNCVAL, (vsync_len << 16) | (hsync_len << 0) |
+                ((mode->flags & DRM_MODE_FLAG_NHSYNC) ? SYNCVAL_HS_POL_ACTIVE_LOW : 0) |
+                ((mode->flags & DRM_MODE_FLAG_NVSYNC) ? SYNCVAL_VS_POL_ACTIVE_LOW : 0));
 
        tc_write(DPIPXLFMT, VS_POL_ACTIVE_LOW | HS_POL_ACTIVE_LOW |
                 DE_POL_ACTIVE_HIGH | SUB_CFG_TYPE_CONFIG1 | DPI_BPP_RGB888);
@@ -829,12 +840,11 @@ static int tc_main_link_setup(struct tc_data *tc)
        if (!tc->mode)
                return -EINVAL;
 
-       /* from excel file - DP0_SrcCtrl */
-       tc_write(DP0_SRCCTRL, DP0_SRCCTRL_SCRMBLDIS | DP0_SRCCTRL_EN810B |
-                DP0_SRCCTRL_LANESKEW | DP0_SRCCTRL_LANES_2 |
-                DP0_SRCCTRL_BW27 | DP0_SRCCTRL_AUTOCORRECT);
-       /* from excel file - DP1_SrcCtrl */
-       tc_write(0x07a0, 0x00003083);
+       tc_write(DP0_SRCCTRL, tc_srcctrl(tc));
+       /* SSCG and BW27 on DP1 must be set to the same as on DP0 */
+       tc_write(DP1_SRCCTRL,
+                (tc->link.spread ? DP0_SRCCTRL_SSCG : 0) |
+                ((tc->link.base.rate != 162000) ? DP0_SRCCTRL_BW27 : 0));
 
        rate = clk_get_rate(tc->refclk);
        switch (rate) {
@@ -855,8 +865,11 @@ static int tc_main_link_setup(struct tc_data *tc)
        }
        value |= SYSCLK_SEL_LSCLK | LSCLK_DIV_2;
        tc_write(SYS_PLLPARAM, value);
+
        /* Setup Main Link */
-       dp_phy_ctrl = BGREN | PWR_SW_EN | BIT(2) | PHY_A0_EN |  PHY_M0_EN;
+       dp_phy_ctrl = BGREN | PWR_SW_EN | PHY_A0_EN | PHY_M0_EN;
+       if (tc->link.base.num_lanes == 2)
+               dp_phy_ctrl |= PHY_2LANE;
        tc_write(DP_PHY_CTRL, dp_phy_ctrl);
        msleep(100);
 
@@ -1105,10 +1118,20 @@ static bool tc_bridge_mode_fixup(struct drm_bridge *bridge,
 static enum drm_mode_status tc_connector_mode_valid(struct drm_connector *connector,
                                   struct drm_display_mode *mode)
 {
+       struct tc_data *tc = connector_to_tc(connector);
+       u32 req, avail;
+       u32 bits_per_pixel = 24;
+
        /* DPI interface clock limitation: upto 154 MHz */
        if (mode->clock > 154000)
                return MODE_CLOCK_HIGH;
 
+       req = mode->clock * bits_per_pixel / 8;
+       avail = tc->link.base.num_lanes * tc->link.base.rate;
+
+       if (req > avail)
+               return MODE_BAD;
+
        return MODE_OK;
 }
 
@@ -1186,7 +1209,8 @@ static int tc_bridge_attach(struct drm_bridge *bridge)
        /* Create eDP connector */
        drm_connector_helper_add(&tc->connector, &tc_connector_helper_funcs);
        ret = drm_connector_init(drm, &tc->connector, &tc_connector_funcs,
-                                DRM_MODE_CONNECTOR_eDP);
+                                tc->panel ? DRM_MODE_CONNECTOR_eDP :
+                                DRM_MODE_CONNECTOR_DisplayPort);
        if (ret)
                return ret;
 
@@ -1195,6 +1219,10 @@ static int tc_bridge_attach(struct drm_bridge *bridge)
 
        drm_display_info_set_bus_formats(&tc->connector.display_info,
                                         &bus_format, 1);
+       tc->connector.display_info.bus_flags =
+               DRM_BUS_FLAG_DE_HIGH |
+               DRM_BUS_FLAG_PIXDATA_NEGEDGE |
+               DRM_BUS_FLAG_SYNC_NEGEDGE;
        drm_connector_attach_encoder(&tc->connector, tc->bridge.encoder);
 
        return 0;
index c408898..9a1f41a 100644 (file)
@@ -1296,12 +1296,11 @@ int drm_mode_atomic_ioctl(struct drm_device *dev,
                        (arg->flags & DRM_MODE_PAGE_FLIP_EVENT))
                return -EINVAL;
 
-       drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
-
        state = drm_atomic_state_alloc(dev);
        if (!state)
                return -ENOMEM;
 
+       drm_modeset_acquire_init(&ctx, DRM_MODESET_ACQUIRE_INTERRUPTIBLE);
        state->acquire_ctx = &ctx;
        state->allow_modeset = !!(arg->flags & DRM_MODE_ATOMIC_ALLOW_MODESET);
 
index 2d6c491..516e82d 100644 (file)
@@ -1273,6 +1273,8 @@ static const struct dpcd_quirk dpcd_quirk_list[] = {
        { OUI(0x00, 0x22, 0xb9), DEVICE_ID_ANY, true, BIT(DP_DPCD_QUIRK_CONSTANT_N) },
        /* LG LP140WF6-SPM1 eDP panel */
        { OUI(0x00, 0x22, 0xb9), DEVICE_ID('s', 'i', 'v', 'a', 'r', 'T'), false, BIT(DP_DPCD_QUIRK_CONSTANT_N) },
+       /* Apple panels need some additional handling to support PSR */
+       { OUI(0x00, 0x10, 0xfa), DEVICE_ID_ANY, false, BIT(DP_DPCD_QUIRK_NO_PSR) }
 };
 
 #undef OUI
index d3af098..d73703a 100644 (file)
@@ -1621,6 +1621,64 @@ static bool drm_fb_pixel_format_equal(const struct fb_var_screeninfo *var_1,
               var_1->transp.msb_right == var_2->transp.msb_right;
 }
 
+static void drm_fb_helper_fill_pixel_fmt(struct fb_var_screeninfo *var,
+                                        u8 depth)
+{
+       switch (depth) {
+       case 8:
+               var->red.offset = 0;
+               var->green.offset = 0;
+               var->blue.offset = 0;
+               var->red.length = 8; /* 8bit DAC */
+               var->green.length = 8;
+               var->blue.length = 8;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               break;
+       case 15:
+               var->red.offset = 10;
+               var->green.offset = 5;
+               var->blue.offset = 0;
+               var->red.length = 5;
+               var->green.length = 5;
+               var->blue.length = 5;
+               var->transp.offset = 15;
+               var->transp.length = 1;
+               break;
+       case 16:
+               var->red.offset = 11;
+               var->green.offset = 5;
+               var->blue.offset = 0;
+               var->red.length = 5;
+               var->green.length = 6;
+               var->blue.length = 5;
+               var->transp.offset = 0;
+               break;
+       case 24:
+               var->red.offset = 16;
+               var->green.offset = 8;
+               var->blue.offset = 0;
+               var->red.length = 8;
+               var->green.length = 8;
+               var->blue.length = 8;
+               var->transp.offset = 0;
+               var->transp.length = 0;
+               break;
+       case 32:
+               var->red.offset = 16;
+               var->green.offset = 8;
+               var->blue.offset = 0;
+               var->red.length = 8;
+               var->green.length = 8;
+               var->blue.length = 8;
+               var->transp.offset = 24;
+               var->transp.length = 8;
+               break;
+       default:
+               break;
+       }
+}
+
 /**
  * drm_fb_helper_check_var - implementation for &fb_ops.fb_check_var
  * @var: screeninfo to check
@@ -1632,9 +1690,14 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
        struct drm_fb_helper *fb_helper = info->par;
        struct drm_framebuffer *fb = fb_helper->fb;
 
-       if (var->pixclock != 0 || in_dbg_master())
+       if (in_dbg_master())
                return -EINVAL;
 
+       if (var->pixclock != 0) {
+               DRM_DEBUG("fbdev emulation doesn't support changing the pixel clock, value of pixclock is ignored\n");
+               var->pixclock = 0;
+       }
+
        if ((drm_format_info_block_width(fb->format, 0) > 1) ||
            (drm_format_info_block_height(fb->format, 0) > 1))
                return -EINVAL;
@@ -1654,6 +1717,20 @@ int drm_fb_helper_check_var(struct fb_var_screeninfo *var,
                return -EINVAL;
        }
 
+       /*
+        * Workaround for SDL 1.2, which is known to be setting all pixel format
+        * fields values to zero in some cases. We treat this situation as a
+        * kind of "use some reasonable autodetected values".
+        */
+       if (!var->red.offset     && !var->green.offset    &&
+           !var->blue.offset    && !var->transp.offset   &&
+           !var->red.length     && !var->green.length    &&
+           !var->blue.length    && !var->transp.length   &&
+           !var->red.msb_right  && !var->green.msb_right &&
+           !var->blue.msb_right && !var->transp.msb_right) {
+               drm_fb_helper_fill_pixel_fmt(var, fb->format->depth);
+       }
+
        /*
         * drm fbdev emulation doesn't support changing the pixel format at all,
         * so reject all pixel format changing requests.
@@ -1967,59 +2044,7 @@ void drm_fb_helper_fill_var(struct fb_info *info, struct drm_fb_helper *fb_helpe
        info->var.yoffset = 0;
        info->var.activate = FB_ACTIVATE_NOW;
 
-       switch (fb->format->depth) {
-       case 8:
-               info->var.red.offset = 0;
-               info->var.green.offset = 0;
-               info->var.blue.offset = 0;
-               info->var.red.length = 8; /* 8bit DAC */
-               info->var.green.length = 8;
-               info->var.blue.length = 8;
-               info->var.transp.offset = 0;
-               info->var.transp.length = 0;
-               break;
-       case 15:
-               info->var.red.offset = 10;
-               info->var.green.offset = 5;
-               info->var.blue.offset = 0;
-               info->var.red.length = 5;
-               info->var.green.length = 5;
-               info->var.blue.length = 5;
-               info->var.transp.offset = 15;
-               info->var.transp.length = 1;
-               break;
-       case 16:
-               info->var.red.offset = 11;
-               info->var.green.offset = 5;
-               info->var.blue.offset = 0;
-               info->var.red.length = 5;
-               info->var.green.length = 6;
-               info->var.blue.length = 5;
-               info->var.transp.offset = 0;
-               break;
-       case 24:
-               info->var.red.offset = 16;
-               info->var.green.offset = 8;
-               info->var.blue.offset = 0;
-               info->var.red.length = 8;
-               info->var.green.length = 8;
-               info->var.blue.length = 8;
-               info->var.transp.offset = 0;
-               info->var.transp.length = 0;
-               break;
-       case 32:
-               info->var.red.offset = 16;
-               info->var.green.offset = 8;
-               info->var.blue.offset = 0;
-               info->var.red.length = 8;
-               info->var.green.length = 8;
-               info->var.blue.length = 8;
-               info->var.transp.offset = 24;
-               info->var.transp.length = 8;
-               break;
-       default:
-               break;
-       }
+       drm_fb_helper_fill_pixel_fmt(&info->var, fb->format->depth);
 
        info->var.xres = fb_width;
        info->var.yres = fb_height;
index 99cba8e..5df1256 100644 (file)
@@ -528,7 +528,8 @@ int drm_mode_create_lease_ioctl(struct drm_device *dev,
 
        object_count = cl->object_count;
 
-       object_ids = memdup_user(u64_to_user_ptr(cl->object_ids), object_count * sizeof(__u32));
+       object_ids = memdup_user(u64_to_user_ptr(cl->object_ids),
+                       array_size(object_count, sizeof(__u32)));
        if (IS_ERR(object_ids))
                return PTR_ERR(object_ids);
 
index cd9bc0c..004191d 100644 (file)
@@ -459,11 +459,11 @@ static int set_property_atomic(struct drm_mode_object *obj,
        struct drm_modeset_acquire_ctx ctx;
        int ret;
 
-       drm_modeset_acquire_init(&ctx, 0);
-
        state = drm_atomic_state_alloc(dev);
        if (!state)
                return -ENOMEM;
+
+       drm_modeset_acquire_init(&ctx, 0);
        state->acquire_ctx = &ctx;
 retry:
        if (prop == state->dev->mode_config.dpms_property) {
index 24a7504..f91e02c 100644 (file)
@@ -758,7 +758,7 @@ int drm_mode_hsync(const struct drm_display_mode *mode)
        if (mode->hsync)
                return mode->hsync;
 
-       if (mode->htotal < 0)
+       if (mode->htotal <= 0)
                return 0;
 
        calc_val = (mode->clock * 1000) / mode->htotal; /* hsync in Hz */
index a9d9df6..693748a 100644 (file)
@@ -61,8 +61,9 @@ drm_dma_handle_t *drm_pci_alloc(struct drm_device * dev, size_t size, size_t ali
                return NULL;
 
        dmah->size = size;
-       dmah->vaddr = dma_zalloc_coherent(&dev->pdev->dev, size, &dmah->busaddr,
-                                               GFP_KERNEL | __GFP_COMP);
+       dmah->vaddr = dma_alloc_coherent(&dev->pdev->dev, size,
+                                        &dmah->busaddr,
+                                        GFP_KERNEL | __GFP_COMP);
 
        if (dmah->vaddr == NULL) {
                kfree(dmah);
index b5475c9..e9f343b 100644 (file)
@@ -2799,6 +2799,7 @@ static int init_broadwell_mmio_info(struct intel_gvt *gvt)
        MMIO_DFH(_MMIO(0xe2a0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(_MMIO(0xe2b0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
        MMIO_DFH(_MMIO(0xe2c0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
+       MMIO_DFH(_MMIO(0x21f0), D_BDW_PLUS, F_CMD_ACCESS, NULL, NULL);
        return 0;
 }
 
index 5af11cf..e1675a0 100644 (file)
@@ -41,7 +41,7 @@ struct intel_gvt_mpt {
        int (*host_init)(struct device *dev, void *gvt, const void *ops);
        void (*host_exit)(struct device *dev, void *gvt);
        int (*attach_vgpu)(void *vgpu, unsigned long *handle);
-       void (*detach_vgpu)(unsigned long handle);
+       void (*detach_vgpu)(void *vgpu);
        int (*inject_msi)(unsigned long handle, u32 addr, u16 data);
        unsigned long (*from_virt_to_mfn)(void *p);
        int (*enable_page_track)(unsigned long handle, u64 gfn);
index c107214..dd3dfd0 100644 (file)
@@ -996,7 +996,7 @@ static int intel_vgpu_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
 {
        unsigned int index;
        u64 virtaddr;
-       unsigned long req_size, pgoff = 0;
+       unsigned long req_size, pgoff, req_start;
        pgprot_t pg_prot;
        struct intel_vgpu *vgpu = mdev_get_drvdata(mdev);
 
@@ -1014,7 +1014,17 @@ static int intel_vgpu_mmap(struct mdev_device *mdev, struct vm_area_struct *vma)
        pg_prot = vma->vm_page_prot;
        virtaddr = vma->vm_start;
        req_size = vma->vm_end - vma->vm_start;
-       pgoff = vgpu_aperture_pa_base(vgpu) >> PAGE_SHIFT;
+       pgoff = vma->vm_pgoff &
+               ((1U << (VFIO_PCI_OFFSET_SHIFT - PAGE_SHIFT)) - 1);
+       req_start = pgoff << PAGE_SHIFT;
+
+       if (!intel_vgpu_in_aperture(vgpu, req_start))
+               return -EINVAL;
+       if (req_start + req_size >
+           vgpu_aperture_offset(vgpu) + vgpu_aperture_sz(vgpu))
+               return -EINVAL;
+
+       pgoff = (gvt_aperture_pa_base(vgpu->gvt) >> PAGE_SHIFT) + pgoff;
 
        return remap_pfn_range(vma, virtaddr, pgoff, req_size, pg_prot);
 }
@@ -1662,9 +1672,21 @@ static int kvmgt_attach_vgpu(void *vgpu, unsigned long *handle)
        return 0;
 }
 
-static void kvmgt_detach_vgpu(unsigned long handle)
+static void kvmgt_detach_vgpu(void *p_vgpu)
 {
-       /* nothing to do here */
+       int i;
+       struct intel_vgpu *vgpu = (struct intel_vgpu *)p_vgpu;
+
+       if (!vgpu->vdev.region)
+               return;
+
+       for (i = 0; i < vgpu->vdev.num_regions; i++)
+               if (vgpu->vdev.region[i].ops->release)
+                       vgpu->vdev.region[i].ops->release(vgpu,
+                                       &vgpu->vdev.region[i]);
+       vgpu->vdev.num_regions = 0;
+       kfree(vgpu->vdev.region);
+       vgpu->vdev.region = NULL;
 }
 
 static int kvmgt_inject_msi(unsigned long handle, u32 addr, u16 data)
index 67f1999..3ed3412 100644 (file)
@@ -101,7 +101,7 @@ static inline void intel_gvt_hypervisor_detach_vgpu(struct intel_vgpu *vgpu)
        if (!intel_gvt_host.mpt->detach_vgpu)
                return;
 
-       intel_gvt_host.mpt->detach_vgpu(vgpu->handle);
+       intel_gvt_host.mpt->detach_vgpu(vgpu);
 }
 
 #define MSI_CAP_CONTROL(offset) (offset + 2)
index 1ad8c5e..55bb788 100644 (file)
@@ -332,6 +332,9 @@ static void release_shadow_wa_ctx(struct intel_shadow_wa_ctx *wa_ctx)
 
        i915_gem_object_unpin_map(wa_ctx->indirect_ctx.obj);
        i915_gem_object_put(wa_ctx->indirect_ctx.obj);
+
+       wa_ctx->indirect_ctx.obj = NULL;
+       wa_ctx->indirect_ctx.shadow_va = NULL;
 }
 
 static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,
@@ -356,6 +359,33 @@ static int set_context_ppgtt_from_shadow(struct intel_vgpu_workload *workload,
        return 0;
 }
 
+static int
+intel_gvt_workload_req_alloc(struct intel_vgpu_workload *workload)
+{
+       struct intel_vgpu *vgpu = workload->vgpu;
+       struct intel_vgpu_submission *s = &vgpu->submission;
+       struct i915_gem_context *shadow_ctx = s->shadow_ctx;
+       struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
+       struct intel_engine_cs *engine = dev_priv->engine[workload->ring_id];
+       struct i915_request *rq;
+       int ret = 0;
+
+       lockdep_assert_held(&dev_priv->drm.struct_mutex);
+
+       if (workload->req)
+               goto out;
+
+       rq = i915_request_alloc(engine, shadow_ctx);
+       if (IS_ERR(rq)) {
+               gvt_vgpu_err("fail to allocate gem request\n");
+               ret = PTR_ERR(rq);
+               goto out;
+       }
+       workload->req = i915_request_get(rq);
+out:
+       return ret;
+}
+
 /**
  * intel_gvt_scan_and_shadow_workload - audit the workload by scanning and
  * shadow it as well, include ringbuffer,wa_ctx and ctx.
@@ -372,12 +402,11 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)
        struct drm_i915_private *dev_priv = vgpu->gvt->dev_priv;
        struct intel_engine_cs *engine = dev_priv->engine[workload->ring_id];
        struct intel_context *ce;
-       struct i915_request *rq;
        int ret;
 
        lockdep_assert_held(&dev_priv->drm.struct_mutex);
 
-       if (workload->req)
+       if (workload->shadow)
                return 0;
 
        ret = set_context_ppgtt_from_shadow(workload, shadow_ctx);
@@ -417,22 +446,8 @@ int intel_gvt_scan_and_shadow_workload(struct intel_vgpu_workload *workload)
                        goto err_shadow;
        }
 
-       rq = i915_request_alloc(engine, shadow_ctx);
-       if (IS_ERR(rq)) {
-               gvt_vgpu_err("fail to allocate gem request\n");
-               ret = PTR_ERR(rq);
-               goto err_shadow;
-       }
-       workload->req = i915_request_get(rq);
-
-       ret = populate_shadow_context(workload);
-       if (ret)
-               goto err_req;
-
+       workload->shadow = true;
        return 0;
-err_req:
-       rq = fetch_and_zero(&workload->req);
-       i915_request_put(rq);
 err_shadow:
        release_shadow_wa_ctx(&workload->wa_ctx);
 err_unpin:
@@ -671,23 +686,31 @@ static int dispatch_workload(struct intel_vgpu_workload *workload)
        mutex_lock(&vgpu->vgpu_lock);
        mutex_lock(&dev_priv->drm.struct_mutex);
 
+       ret = intel_gvt_workload_req_alloc(workload);
+       if (ret)
+               goto err_req;
+
        ret = intel_gvt_scan_and_shadow_workload(workload);
        if (ret)
                goto out;
 
-       ret = prepare_workload(workload);
+       ret = populate_shadow_context(workload);
+       if (ret) {
+               release_shadow_wa_ctx(&workload->wa_ctx);
+               goto out;
+       }
 
+       ret = prepare_workload(workload);
 out:
-       if (ret)
-               workload->status = ret;
-
        if (!IS_ERR_OR_NULL(workload->req)) {
                gvt_dbg_sched("ring id %d submit workload to i915 %p\n",
                                ring_id, workload->req);
                i915_request_add(workload->req);
                workload->dispatched = true;
        }
-
+err_req:
+       if (ret)
+               workload->status = ret;
        mutex_unlock(&dev_priv->drm.struct_mutex);
        mutex_unlock(&vgpu->vgpu_lock);
        return ret;
@@ -891,11 +914,6 @@ static void complete_current_workload(struct intel_gvt *gvt, int ring_id)
 
        list_del_init(&workload->list);
 
-       if (!workload->status) {
-               release_shadow_batch_buffer(workload);
-               release_shadow_wa_ctx(&workload->wa_ctx);
-       }
-
        if (workload->status || (vgpu->resetting_eng & ENGINE_MASK(ring_id))) {
                /* if workload->status is not successful means HW GPU
                 * has occurred GPU hang or something wrong with i915/GVT,
@@ -1263,6 +1281,9 @@ void intel_vgpu_destroy_workload(struct intel_vgpu_workload *workload)
 {
        struct intel_vgpu_submission *s = &workload->vgpu->submission;
 
+       release_shadow_batch_buffer(workload);
+       release_shadow_wa_ctx(&workload->wa_ctx);
+
        if (workload->shadow_mm)
                intel_vgpu_mm_put(workload->shadow_mm);
 
index ca5529d..2065cba 100644 (file)
@@ -83,6 +83,7 @@ struct intel_vgpu_workload {
        struct i915_request *req;
        /* if this workload has been dispatched to i915? */
        bool dispatched;
+       bool shadow;      /* if workload has done shadow of guest request */
        int status;
 
        struct intel_vgpu_mm *shadow_mm;
index 38dcee1..40a61ef 100644 (file)
@@ -984,8 +984,8 @@ static int i915_gpu_info_open(struct inode *inode, struct file *file)
        intel_runtime_pm_get(i915);
        gpu = i915_capture_gpu_state(i915);
        intel_runtime_pm_put(i915);
-       if (!gpu)
-               return -ENOMEM;
+       if (IS_ERR(gpu))
+               return PTR_ERR(gpu);
 
        file->private_data = gpu;
        return 0;
@@ -1018,7 +1018,13 @@ i915_error_state_write(struct file *filp,
 
 static int i915_error_state_open(struct inode *inode, struct file *file)
 {
-       file->private_data = i915_first_error_state(inode->i_private);
+       struct i915_gpu_state *error;
+
+       error = i915_first_error_state(inode->i_private);
+       if (IS_ERR(error))
+               return PTR_ERR(error);
+
+       file->private_data  = error;
        return 0;
 }
 
index 216f52b..c882ea9 100644 (file)
@@ -1824,6 +1824,16 @@ i915_gem_sw_finish_ioctl(struct drm_device *dev, void *data,
        return 0;
 }
 
+static inline bool
+__vma_matches(struct vm_area_struct *vma, struct file *filp,
+             unsigned long addr, unsigned long size)
+{
+       if (vma->vm_file != filp)
+               return false;
+
+       return vma->vm_start == addr && (vma->vm_end - vma->vm_start) == size;
+}
+
 /**
  * i915_gem_mmap_ioctl - Maps the contents of an object, returning the address
  *                      it is mapped to.
@@ -1882,7 +1892,7 @@ i915_gem_mmap_ioctl(struct drm_device *dev, void *data,
                        return -EINTR;
                }
                vma = find_vma(mm, addr);
-               if (vma)
+               if (vma && __vma_matches(vma, obj->base.filp, addr, args->size))
                        vma->vm_page_prot =
                                pgprot_writecombine(vm_get_page_prot(vma->vm_flags));
                else
index add1fe7..bd17dd1 100644 (file)
@@ -2075,6 +2075,7 @@ static struct i915_vma *pd_vma_create(struct gen6_hw_ppgtt *ppgtt, int size)
 int gen6_ppgtt_pin(struct i915_hw_ppgtt *base)
 {
        struct gen6_hw_ppgtt *ppgtt = to_gen6_ppgtt(base);
+       int err;
 
        /*
         * Workaround the limited maximum vma->pin_count and the aliasing_ppgtt
@@ -2090,9 +2091,17 @@ int gen6_ppgtt_pin(struct i915_hw_ppgtt *base)
         * allocator works in address space sizes, so it's multiplied by page
         * size. We allocate at the top of the GTT to avoid fragmentation.
         */
-       return i915_vma_pin(ppgtt->vma,
-                           0, GEN6_PD_ALIGN,
-                           PIN_GLOBAL | PIN_HIGH);
+       err = i915_vma_pin(ppgtt->vma,
+                          0, GEN6_PD_ALIGN,
+                          PIN_GLOBAL | PIN_HIGH);
+       if (err)
+               goto unpin;
+
+       return 0;
+
+unpin:
+       ppgtt->pin_count = 0;
+       return err;
 }
 
 void gen6_ppgtt_unpin(struct i915_hw_ppgtt *base)
index 0746512..3f9ce40 100644 (file)
@@ -1907,9 +1907,16 @@ i915_capture_gpu_state(struct drm_i915_private *i915)
 {
        struct i915_gpu_state *error;
 
+       /* Check if GPU capture has been disabled */
+       error = READ_ONCE(i915->gpu_error.first_error);
+       if (IS_ERR(error))
+               return error;
+
        error = kzalloc(sizeof(*error), GFP_ATOMIC);
-       if (!error)
-               return NULL;
+       if (!error) {
+               i915_disable_error_state(i915, -ENOMEM);
+               return ERR_PTR(-ENOMEM);
+       }
 
        kref_init(&error->ref);
        error->i915 = i915;
@@ -1945,11 +1952,8 @@ void i915_capture_error_state(struct drm_i915_private *i915,
                return;
 
        error = i915_capture_gpu_state(i915);
-       if (!error) {
-               DRM_DEBUG_DRIVER("out of memory, not capturing error state\n");
-               i915_disable_error_state(i915, -ENOMEM);
+       if (IS_ERR(error))
                return;
-       }
 
        i915_error_capture_msg(i915, error, engine_mask, error_msg);
        DRM_INFO("%s\n", error->error_msg);
@@ -1987,7 +1991,7 @@ i915_first_error_state(struct drm_i915_private *i915)
 
        spin_lock_irq(&i915->gpu_error.lock);
        error = i915->gpu_error.first_error;
-       if (error)
+       if (!IS_ERR_OR_NULL(error))
                i915_gpu_state_get(error);
        spin_unlock_irq(&i915->gpu_error.lock);
 
@@ -2000,10 +2004,11 @@ void i915_reset_error_state(struct drm_i915_private *i915)
 
        spin_lock_irq(&i915->gpu_error.lock);
        error = i915->gpu_error.first_error;
-       i915->gpu_error.first_error = NULL;
+       if (error != ERR_PTR(-ENODEV)) /* if disabled, always disabled */
+               i915->gpu_error.first_error = NULL;
        spin_unlock_irq(&i915->gpu_error.lock);
 
-       if (!IS_ERR(error))
+       if (!IS_ERR_OR_NULL(error))
                i915_gpu_state_put(error);
 }
 
index d6c8f8f..017fc60 100644 (file)
@@ -594,7 +594,8 @@ static void i915_pmu_enable(struct perf_event *event)
         * Update the bitmask of enabled events and increment
         * the event reference counter.
         */
-       GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
+       BUILD_BUG_ON(ARRAY_SIZE(i915->pmu.enable_count) != I915_PMU_MASK_BITS);
+       GEM_BUG_ON(bit >= ARRAY_SIZE(i915->pmu.enable_count));
        GEM_BUG_ON(i915->pmu.enable_count[bit] == ~0);
        i915->pmu.enable |= BIT_ULL(bit);
        i915->pmu.enable_count[bit]++;
@@ -615,11 +616,16 @@ static void i915_pmu_enable(struct perf_event *event)
                engine = intel_engine_lookup_user(i915,
                                                  engine_event_class(event),
                                                  engine_event_instance(event));
-               GEM_BUG_ON(!engine);
-               engine->pmu.enable |= BIT(sample);
 
-               GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
+               BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.enable_count) !=
+                            I915_ENGINE_SAMPLE_COUNT);
+               BUILD_BUG_ON(ARRAY_SIZE(engine->pmu.sample) !=
+                            I915_ENGINE_SAMPLE_COUNT);
+               GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
+               GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
                GEM_BUG_ON(engine->pmu.enable_count[sample] == ~0);
+
+               engine->pmu.enable |= BIT(sample);
                engine->pmu.enable_count[sample]++;
        }
 
@@ -649,9 +655,11 @@ static void i915_pmu_disable(struct perf_event *event)
                engine = intel_engine_lookup_user(i915,
                                                  engine_event_class(event),
                                                  engine_event_instance(event));
-               GEM_BUG_ON(!engine);
-               GEM_BUG_ON(sample >= I915_PMU_SAMPLE_BITS);
+
+               GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.enable_count));
+               GEM_BUG_ON(sample >= ARRAY_SIZE(engine->pmu.sample));
                GEM_BUG_ON(engine->pmu.enable_count[sample] == 0);
+
                /*
                 * Decrement the reference count and clear the enabled
                 * bitmask when the last listener on an event goes away.
@@ -660,7 +668,7 @@ static void i915_pmu_disable(struct perf_event *event)
                        engine->pmu.enable &= ~BIT(sample);
        }
 
-       GEM_BUG_ON(bit >= I915_PMU_MASK_BITS);
+       GEM_BUG_ON(bit >= ARRAY_SIZE(i915->pmu.enable_count));
        GEM_BUG_ON(i915->pmu.enable_count[bit] == 0);
        /*
         * Decrement the reference count and clear the enabled
index 7f164ca..b3728c5 100644 (file)
@@ -31,6 +31,8 @@ enum {
        ((1 << I915_PMU_SAMPLE_BITS) + \
         (I915_PMU_LAST + 1 - __I915_PMU_OTHER(0)))
 
+#define I915_ENGINE_SAMPLE_COUNT (I915_SAMPLE_SEMA + 1)
+
 struct i915_pmu_sample {
        u64 cur;
 };
index 0a7d605..067054c 100644 (file)
@@ -1790,7 +1790,7 @@ enum i915_power_well_id {
 #define _CNL_PORT_TX_C_LN0_OFFSET              0x162C40
 #define _CNL_PORT_TX_D_LN0_OFFSET              0x162E40
 #define _CNL_PORT_TX_F_LN0_OFFSET              0x162840
-#define _CNL_PORT_TX_DW_GRP(port, dw)  (_PICK((port), \
+#define _CNL_PORT_TX_DW_GRP(dw, port)  (_PICK((port), \
                                               _CNL_PORT_TX_AE_GRP_OFFSET, \
                                               _CNL_PORT_TX_B_GRP_OFFSET, \
                                               _CNL_PORT_TX_B_GRP_OFFSET, \
@@ -1798,7 +1798,7 @@ enum i915_power_well_id {
                                               _CNL_PORT_TX_AE_GRP_OFFSET, \
                                               _CNL_PORT_TX_F_GRP_OFFSET) + \
                                               4 * (dw))
-#define _CNL_PORT_TX_DW_LN0(port, dw)  (_PICK((port), \
+#define _CNL_PORT_TX_DW_LN0(dw, port)  (_PICK((port), \
                                               _CNL_PORT_TX_AE_LN0_OFFSET, \
                                               _CNL_PORT_TX_B_LN0_OFFSET, \
                                               _CNL_PORT_TX_B_LN0_OFFSET, \
@@ -1834,9 +1834,9 @@ enum i915_power_well_id {
 
 #define _CNL_PORT_TX_DW4_LN0_AE                0x162450
 #define _CNL_PORT_TX_DW4_LN1_AE                0x1624D0
-#define CNL_PORT_TX_DW4_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP((port), 4))
-#define CNL_PORT_TX_DW4_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0((port), 4))
-#define CNL_PORT_TX_DW4_LN(port, ln)   _MMIO(_CNL_PORT_TX_DW_LN0((port), 4) + \
+#define CNL_PORT_TX_DW4_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP(4, (port)))
+#define CNL_PORT_TX_DW4_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)))
+#define CNL_PORT_TX_DW4_LN(port, ln)   _MMIO(_CNL_PORT_TX_DW_LN0(4, (port)) + \
                                           ((ln) * (_CNL_PORT_TX_DW4_LN1_AE - \
                                                    _CNL_PORT_TX_DW4_LN0_AE)))
 #define ICL_PORT_TX_DW4_AUX(port)      _MMIO(_ICL_PORT_TX_DW_AUX(4, port))
@@ -1864,8 +1864,12 @@ enum i915_power_well_id {
 #define   RTERM_SELECT(x)              ((x) << 3)
 #define   RTERM_SELECT_MASK            (0x7 << 3)
 
-#define CNL_PORT_TX_DW7_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP((port), 7))
-#define CNL_PORT_TX_DW7_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0((port), 7))
+#define CNL_PORT_TX_DW7_GRP(port)      _MMIO(_CNL_PORT_TX_DW_GRP(7, (port)))
+#define CNL_PORT_TX_DW7_LN0(port)      _MMIO(_CNL_PORT_TX_DW_LN0(7, (port)))
+#define ICL_PORT_TX_DW7_AUX(port)      _MMIO(_ICL_PORT_TX_DW_AUX(7, port))
+#define ICL_PORT_TX_DW7_GRP(port)      _MMIO(_ICL_PORT_TX_DW_GRP(7, port))
+#define ICL_PORT_TX_DW7_LN0(port)      _MMIO(_ICL_PORT_TX_DW_LN(7, 0, port))
+#define ICL_PORT_TX_DW7_LN(port, ln)   _MMIO(_ICL_PORT_TX_DW_LN(7, ln, port))
 #define   N_SCALAR(x)                  ((x) << 24)
 #define   N_SCALAR_MASK                        (0x7F << 24)
 
index 535caeb..c0cfe7a 100644 (file)
@@ -521,7 +521,9 @@ static ssize_t error_state_read(struct file *filp, struct kobject *kobj,
        ssize_t ret;
 
        gpu = i915_first_error_state(i915);
-       if (gpu) {
+       if (IS_ERR(gpu)) {
+               ret = PTR_ERR(gpu);
+       } else if (gpu) {
                ret = i915_gpu_state_copy_to_buffer(gpu, buf, off, count);
                i915_gpu_state_put(gpu);
        } else {
index f3e1d6a..7edce1b 100644 (file)
@@ -494,103 +494,58 @@ static const struct cnl_ddi_buf_trans cnl_ddi_translations_edp_1_05V[] = {
        { 0x2, 0x7F, 0x3F, 0x00, 0x00 },        /* 400   400      0.0   */
 };
 
-struct icl_combo_phy_ddi_buf_trans {
-       u32 dw2_swing_select;
-       u32 dw2_swing_scalar;
-       u32 dw4_scaling;
-};
-
-/* Voltage Swing Programming for VccIO 0.85V for DP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_85V[] = {
-                               /* Voltage mV  db    */
-       { 0x2, 0x98, 0x0018 },  /* 400         0.0   */
-       { 0x2, 0x98, 0x3015 },  /* 400         3.5   */
-       { 0x2, 0x98, 0x6012 },  /* 400         6.0   */
-       { 0x2, 0x98, 0x900F },  /* 400         9.5   */
-       { 0xB, 0x70, 0x0018 },  /* 600         0.0   */
-       { 0xB, 0x70, 0x3015 },  /* 600         3.5   */
-       { 0xB, 0x70, 0x6012 },  /* 600         6.0   */
-       { 0x5, 0x00, 0x0018 },  /* 800         0.0   */
-       { 0x5, 0x00, 0x3015 },  /* 800         3.5   */
-       { 0x6, 0x98, 0x0018 },  /* 1200        0.0   */
-};
-
-/* FIXME - After table is updated in Bspec */
-/* Voltage Swing Programming for VccIO 0.85V for eDP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_85V[] = {
-                               /* Voltage mV  db    */
-       { 0x0, 0x00, 0x00 },    /* 200         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 200         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         6.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 250         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 350         0.0   */
-};
-
-/* Voltage Swing Programming for VccIO 0.95V for DP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_0_95V[] = {
-                               /* Voltage mV  db    */
-       { 0x2, 0x98, 0x0018 },  /* 400         0.0   */
-       { 0x2, 0x98, 0x3015 },  /* 400         3.5   */
-       { 0x2, 0x98, 0x6012 },  /* 400         6.0   */
-       { 0x2, 0x98, 0x900F },  /* 400         9.5   */
-       { 0x4, 0x98, 0x0018 },  /* 600         0.0   */
-       { 0x4, 0x98, 0x3015 },  /* 600         3.5   */
-       { 0x4, 0x98, 0x6012 },  /* 600         6.0   */
-       { 0x5, 0x76, 0x0018 },  /* 800         0.0   */
-       { 0x5, 0x76, 0x3015 },  /* 800         3.5   */
-       { 0x6, 0x98, 0x0018 },  /* 1200        0.0   */
+/* icl_combo_phy_ddi_translations */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hbr2[] = {
+                                               /* NT mV Trans mV db    */
+       { 0xA, 0x35, 0x3F, 0x00, 0x00 },        /* 350   350      0.0   */
+       { 0xA, 0x4F, 0x37, 0x00, 0x08 },        /* 350   500      3.1   */
+       { 0xC, 0x71, 0x2F, 0x00, 0x10 },        /* 350   700      6.0   */
+       { 0x6, 0x7F, 0x2B, 0x00, 0x14 },        /* 350   900      8.2   */
+       { 0xA, 0x4C, 0x3F, 0x00, 0x00 },        /* 500   500      0.0   */
+       { 0xC, 0x73, 0x34, 0x00, 0x0B },        /* 500   700      2.9   */
+       { 0x6, 0x7F, 0x2F, 0x00, 0x10 },        /* 500   900      5.1   */
+       { 0xC, 0x6C, 0x3C, 0x00, 0x03 },        /* 650   700      0.6   */
+       { 0x6, 0x7F, 0x35, 0x00, 0x0A },        /* 600   900      3.5   */
+       { 0x6, 0x7F, 0x3F, 0x00, 0x00 },        /* 900   900      0.0   */
 };
 
-/* FIXME - After table is updated in Bspec */
-/* Voltage Swing Programming for VccIO 0.95V for eDP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_0_95V[] = {
-                               /* Voltage mV  db    */
-       { 0x0, 0x00, 0x00 },    /* 200         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 200         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         6.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 250         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 350         0.0   */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr2[] = {
+                                               /* NT mV Trans mV db    */
+       { 0x0, 0x7F, 0x3F, 0x00, 0x00 },        /* 200   200      0.0   */
+       { 0x8, 0x7F, 0x38, 0x00, 0x07 },        /* 200   250      1.9   */
+       { 0x1, 0x7F, 0x33, 0x00, 0x0C },        /* 200   300      3.5   */
+       { 0x9, 0x7F, 0x31, 0x00, 0x0E },        /* 200   350      4.9   */
+       { 0x8, 0x7F, 0x3F, 0x00, 0x00 },        /* 250   250      0.0   */
+       { 0x1, 0x7F, 0x38, 0x00, 0x07 },        /* 250   300      1.6   */
+       { 0x9, 0x7F, 0x35, 0x00, 0x0A },        /* 250   350      2.9   */
+       { 0x1, 0x7F, 0x3F, 0x00, 0x00 },        /* 300   300      0.0   */
+       { 0x9, 0x7F, 0x38, 0x00, 0x07 },        /* 300   350      1.3   */
+       { 0x9, 0x7F, 0x3F, 0x00, 0x00 },        /* 350   350      0.0   */
 };
 
-/* Voltage Swing Programming for VccIO 1.05V for DP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_dp_hdmi_1_05V[] = {
-                               /* Voltage mV  db    */
-       { 0x2, 0x98, 0x0018 },  /* 400         0.0   */
-       { 0x2, 0x98, 0x3015 },  /* 400         3.5   */
-       { 0x2, 0x98, 0x6012 },  /* 400         6.0   */
-       { 0x2, 0x98, 0x900F },  /* 400         9.5   */
-       { 0x4, 0x98, 0x0018 },  /* 600         0.0   */
-       { 0x4, 0x98, 0x3015 },  /* 600         3.5   */
-       { 0x4, 0x98, 0x6012 },  /* 600         6.0   */
-       { 0x5, 0x71, 0x0018 },  /* 800         0.0   */
-       { 0x5, 0x71, 0x3015 },  /* 800         3.5   */
-       { 0x6, 0x98, 0x0018 },  /* 1200        0.0   */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_edp_hbr3[] = {
+                                               /* NT mV Trans mV db    */
+       { 0xA, 0x35, 0x3F, 0x00, 0x00 },        /* 350   350      0.0   */
+       { 0xA, 0x4F, 0x37, 0x00, 0x08 },        /* 350   500      3.1   */
+       { 0xC, 0x71, 0x2F, 0x00, 0x10 },        /* 350   700      6.0   */
+       { 0x6, 0x7F, 0x2B, 0x00, 0x14 },        /* 350   900      8.2   */
+       { 0xA, 0x4C, 0x3F, 0x00, 0x00 },        /* 500   500      0.0   */
+       { 0xC, 0x73, 0x34, 0x00, 0x0B },        /* 500   700      2.9   */
+       { 0x6, 0x7F, 0x2F, 0x00, 0x10 },        /* 500   900      5.1   */
+       { 0xC, 0x6C, 0x3C, 0x00, 0x03 },        /* 650   700      0.6   */
+       { 0x6, 0x7F, 0x35, 0x00, 0x0A },        /* 600   900      3.5   */
+       { 0x6, 0x7F, 0x3F, 0x00, 0x00 },        /* 900   900      0.0   */
 };
 
-/* FIXME - After table is updated in Bspec */
-/* Voltage Swing Programming for VccIO 1.05V for eDP */
-static const struct icl_combo_phy_ddi_buf_trans icl_combo_phy_ddi_translations_edp_1_05V[] = {
-                               /* Voltage mV  db    */
-       { 0x0, 0x00, 0x00 },    /* 200         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 200         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 200         6.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 250         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 250         4.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         0.0   */
-       { 0x0, 0x00, 0x00 },    /* 300         1.5   */
-       { 0x0, 0x00, 0x00 },    /* 350         0.0   */
+static const struct cnl_ddi_buf_trans icl_combo_phy_ddi_translations_hdmi[] = {
+                                               /* NT mV Trans mV db    */
+       { 0xA, 0x60, 0x3F, 0x00, 0x00 },        /* 450   450      0.0   */
+       { 0xB, 0x73, 0x36, 0x00, 0x09 },        /* 450   650      3.2   */
+       { 0x6, 0x7F, 0x31, 0x00, 0x0E },        /* 450   850      5.5   */
+       { 0xB, 0x73, 0x3F, 0x00, 0x00 },        /* 650   650      0.0   ALS */
+       { 0x6, 0x7F, 0x37, 0x00, 0x08 },        /* 650   850      2.3   */
+       { 0x6, 0x7F, 0x3F, 0x00, 0x00 },        /* 850   850      0.0   */
+       { 0x6, 0x7F, 0x35, 0x00, 0x0A },        /* 600   850      3.0   */
 };
 
 struct icl_mg_phy_ddi_buf_trans {
@@ -871,43 +826,23 @@ cnl_get_buf_trans_edp(struct drm_i915_private *dev_priv, int *n_entries)
        }
 }
 
-static const struct icl_combo_phy_ddi_buf_trans *
+static const struct cnl_ddi_buf_trans *
 icl_get_combo_buf_trans(struct drm_i915_private *dev_priv, enum port port,
-                       int type, int *n_entries)
+                       int type, int rate, int *n_entries)
 {
-       u32 voltage = I915_READ(ICL_PORT_COMP_DW3(port)) & VOLTAGE_INFO_MASK;
-
-       if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
-               switch (voltage) {
-               case VOLTAGE_INFO_0_85V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_85V);
-                       return icl_combo_phy_ddi_translations_edp_0_85V;
-               case VOLTAGE_INFO_0_95V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_0_95V);
-                       return icl_combo_phy_ddi_translations_edp_0_95V;
-               case VOLTAGE_INFO_1_05V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_1_05V);
-                       return icl_combo_phy_ddi_translations_edp_1_05V;
-               default:
-                       MISSING_CASE(voltage);
-                       return NULL;
-               }
-       } else {
-               switch (voltage) {
-               case VOLTAGE_INFO_0_85V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_85V);
-                       return icl_combo_phy_ddi_translations_dp_hdmi_0_85V;
-               case VOLTAGE_INFO_0_95V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_0_95V);
-                       return icl_combo_phy_ddi_translations_dp_hdmi_0_95V;
-               case VOLTAGE_INFO_1_05V:
-                       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hdmi_1_05V);
-                       return icl_combo_phy_ddi_translations_dp_hdmi_1_05V;
-               default:
-                       MISSING_CASE(voltage);
-                       return NULL;
-               }
+       if (type == INTEL_OUTPUT_HDMI) {
+               *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_hdmi);
+               return icl_combo_phy_ddi_translations_hdmi;
+       } else if (rate > 540000 && type == INTEL_OUTPUT_EDP) {
+               *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr3);
+               return icl_combo_phy_ddi_translations_edp_hbr3;
+       } else if (type == INTEL_OUTPUT_EDP && dev_priv->vbt.edp.low_vswing) {
+               *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_edp_hbr2);
+               return icl_combo_phy_ddi_translations_edp_hbr2;
        }
+
+       *n_entries = ARRAY_SIZE(icl_combo_phy_ddi_translations_dp_hbr2);
+       return icl_combo_phy_ddi_translations_dp_hbr2;
 }
 
 static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port port)
@@ -918,8 +853,8 @@ static int intel_ddi_hdmi_level(struct drm_i915_private *dev_priv, enum port por
 
        if (IS_ICELAKE(dev_priv)) {
                if (intel_port_is_combophy(dev_priv, port))
-                       icl_get_combo_buf_trans(dev_priv, port,
-                                               INTEL_OUTPUT_HDMI, &n_entries);
+                       icl_get_combo_buf_trans(dev_priv, port, INTEL_OUTPUT_HDMI,
+                                               0, &n_entries);
                else
                        n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);
                default_entry = n_entries - 1;
@@ -1086,7 +1021,7 @@ static uint32_t icl_pll_to_ddi_pll_sel(struct intel_encoder *encoder,
                        return DDI_CLK_SEL_TBT_810;
                default:
                        MISSING_CASE(clock);
-                       break;
+                       return DDI_CLK_SEL_NONE;
                }
        case DPLL_ID_ICL_MGPLL1:
        case DPLL_ID_ICL_MGPLL2:
@@ -2275,13 +2210,14 @@ static void bxt_ddi_vswing_sequence(struct intel_encoder *encoder,
 u8 intel_ddi_dp_voltage_max(struct intel_encoder *encoder)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
+       struct intel_dp *intel_dp = enc_to_intel_dp(&encoder->base);
        enum port port = encoder->port;
        int n_entries;
 
        if (IS_ICELAKE(dev_priv)) {
                if (intel_port_is_combophy(dev_priv, port))
                        icl_get_combo_buf_trans(dev_priv, port, encoder->type,
-                                               &n_entries);
+                                               intel_dp->link_rate, &n_entries);
                else
                        n_entries = ARRAY_SIZE(icl_mg_phy_ddi_translations);
        } else if (IS_CANNONLAKE(dev_priv)) {
@@ -2462,14 +2398,15 @@ static void cnl_ddi_vswing_sequence(struct intel_encoder *encoder,
 }
 
 static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
-                                        u32 level, enum port port, int type)
+                                       u32 level, enum port port, int type,
+                                       int rate)
 {
-       const struct icl_combo_phy_ddi_buf_trans *ddi_translations = NULL;
+       const struct cnl_ddi_buf_trans *ddi_translations = NULL;
        u32 n_entries, val;
        int ln;
 
        ddi_translations = icl_get_combo_buf_trans(dev_priv, port, type,
-                                                  &n_entries);
+                                                  rate, &n_entries);
        if (!ddi_translations)
                return;
 
@@ -2478,34 +2415,23 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
                level = n_entries - 1;
        }
 
-       /* Set PORT_TX_DW5 Rterm Sel to 110b. */
+       /* Set PORT_TX_DW5 */
        val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
-       val &= ~RTERM_SELECT_MASK;
+       val &= ~(SCALING_MODE_SEL_MASK | RTERM_SELECT_MASK |
+                 TAP2_DISABLE | TAP3_DISABLE);
+       val |= SCALING_MODE_SEL(0x2);
        val |= RTERM_SELECT(0x6);
-       I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
-
-       /* Program PORT_TX_DW5 */
-       val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
-       /* Set DisableTap2 and DisableTap3 if MIPI DSI
-        * Clear DisableTap2 and DisableTap3 for all other Ports
-        */
-       if (type == INTEL_OUTPUT_DSI) {
-               val |= TAP2_DISABLE;
-               val |= TAP3_DISABLE;
-       } else {
-               val &= ~TAP2_DISABLE;
-               val &= ~TAP3_DISABLE;
-       }
+       val |= TAP3_DISABLE;
        I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
 
        /* Program PORT_TX_DW2 */
        val = I915_READ(ICL_PORT_TX_DW2_LN0(port));
        val &= ~(SWING_SEL_LOWER_MASK | SWING_SEL_UPPER_MASK |
                 RCOMP_SCALAR_MASK);
-       val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_select);
-       val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_select);
+       val |= SWING_SEL_UPPER(ddi_translations[level].dw2_swing_sel);
+       val |= SWING_SEL_LOWER(ddi_translations[level].dw2_swing_sel);
        /* Program Rcomp scalar for every table entry */
-       val |= RCOMP_SCALAR(ddi_translations[level].dw2_swing_scalar);
+       val |= RCOMP_SCALAR(0x98);
        I915_WRITE(ICL_PORT_TX_DW2_GRP(port), val);
 
        /* Program PORT_TX_DW4 */
@@ -2514,9 +2440,17 @@ static void icl_ddi_combo_vswing_program(struct drm_i915_private *dev_priv,
                val = I915_READ(ICL_PORT_TX_DW4_LN(port, ln));
                val &= ~(POST_CURSOR_1_MASK | POST_CURSOR_2_MASK |
                         CURSOR_COEFF_MASK);
-               val |= ddi_translations[level].dw4_scaling;
+               val |= POST_CURSOR_1(ddi_translations[level].dw4_post_cursor_1);
+               val |= POST_CURSOR_2(ddi_translations[level].dw4_post_cursor_2);
+               val |= CURSOR_COEFF(ddi_translations[level].dw4_cursor_coeff);
                I915_WRITE(ICL_PORT_TX_DW4_LN(port, ln), val);
        }
+
+       /* Program PORT_TX_DW7 */
+       val = I915_READ(ICL_PORT_TX_DW7_LN0(port));
+       val &= ~N_SCALAR_MASK;
+       val |= N_SCALAR(ddi_translations[level].dw7_n_scalar);
+       I915_WRITE(ICL_PORT_TX_DW7_GRP(port), val);
 }
 
 static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
@@ -2581,7 +2515,7 @@ static void icl_combo_phy_ddi_vswing_sequence(struct intel_encoder *encoder,
        I915_WRITE(ICL_PORT_TX_DW5_GRP(port), val);
 
        /* 5. Program swing and de-emphasis */
-       icl_ddi_combo_vswing_program(dev_priv, level, port, type);
+       icl_ddi_combo_vswing_program(dev_priv, level, port, type, rate);
 
        /* 6. Set training enable to trigger update */
        val = I915_READ(ICL_PORT_TX_DW5_LN0(port));
index 3da9c0f..2481281 100644 (file)
@@ -15415,16 +15415,45 @@ static void intel_sanitize_crtc(struct intel_crtc *crtc,
        }
 }
 
+static bool has_bogus_dpll_config(const struct intel_crtc_state *crtc_state)
+{
+       struct drm_i915_private *dev_priv = to_i915(crtc_state->base.crtc->dev);
+
+       /*
+        * Some SNB BIOSen (eg. ASUS K53SV) are known to misprogram
+        * the hardware when a high res displays plugged in. DPLL P
+        * divider is zero, and the pipe timings are bonkers. We'll
+        * try to disable everything in that case.
+        *
+        * FIXME would be nice to be able to sanitize this state
+        * without several WARNs, but for now let's take the easy
+        * road.
+        */
+       return IS_GEN6(dev_priv) &&
+               crtc_state->base.active &&
+               crtc_state->shared_dpll &&
+               crtc_state->port_clock == 0;
+}
+
 static void intel_sanitize_encoder(struct intel_encoder *encoder)
 {
        struct drm_i915_private *dev_priv = to_i915(encoder->base.dev);
        struct intel_connector *connector;
+       struct intel_crtc *crtc = to_intel_crtc(encoder->base.crtc);
+       struct intel_crtc_state *crtc_state = crtc ?
+               to_intel_crtc_state(crtc->base.state) : NULL;
 
        /* We need to check both for a crtc link (meaning that the
         * encoder is active and trying to read from a pipe) and the
         * pipe itself being active. */
-       bool has_active_crtc = encoder->base.crtc &&
-               to_intel_crtc(encoder->base.crtc)->active;
+       bool has_active_crtc = crtc_state &&
+               crtc_state->base.active;
+
+       if (crtc_state && has_bogus_dpll_config(crtc_state)) {
+               DRM_DEBUG_KMS("BIOS has misprogrammed the hardware. Disabling pipe %c\n",
+                             pipe_name(crtc->pipe));
+               has_active_crtc = false;
+       }
 
        connector = intel_encoder_find_connector(encoder);
        if (connector && !has_active_crtc) {
@@ -15435,16 +15464,25 @@ static void intel_sanitize_encoder(struct intel_encoder *encoder)
                /* Connector is active, but has no active pipe. This is
                 * fallout from our resume register restoring. Disable
                 * the encoder manually again. */
-               if (encoder->base.crtc) {
-                       struct drm_crtc_state *crtc_state = encoder->base.crtc->state;
+               if (crtc_state) {
+                       struct drm_encoder *best_encoder;
 
                        DRM_DEBUG_KMS("[ENCODER:%d:%s] manually disabled\n",
                                      encoder->base.base.id,
                                      encoder->base.name);
+
+                       /* avoid oopsing in case the hooks consult best_encoder */
+                       best_encoder = connector->base.state->best_encoder;
+                       connector->base.state->best_encoder = &encoder->base;
+
                        if (encoder->disable)
-                               encoder->disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state);
+                               encoder->disable(encoder, crtc_state,
+                                                connector->base.state);
                        if (encoder->post_disable)
-                               encoder->post_disable(encoder, to_intel_crtc_state(crtc_state), connector->base.state);
+                               encoder->post_disable(encoder, crtc_state,
+                                                     connector->base.state);
+
+                       connector->base.state->best_encoder = best_encoder;
                }
                encoder->base.crtc = NULL;
 
index fdd2cbc..22a7460 100644 (file)
@@ -304,9 +304,11 @@ static int cnl_max_source_rate(struct intel_dp *intel_dp)
 static int icl_max_source_rate(struct intel_dp *intel_dp)
 {
        struct intel_digital_port *dig_port = dp_to_dig_port(intel_dp);
+       struct drm_i915_private *dev_priv = to_i915(dig_port->base.base.dev);
        enum port port = dig_port->base.port;
 
-       if (port == PORT_B)
+       if (intel_port_is_combophy(dev_priv, port) &&
+           !intel_dp_is_edp(intel_dp))
                return 540000;
 
        return 810000;
index f94a04b..e9ddeaf 100644 (file)
@@ -209,6 +209,16 @@ struct intel_fbdev {
        unsigned long vma_flags;
        async_cookie_t cookie;
        int preferred_bpp;
+
+       /* Whether or not fbdev hpd processing is temporarily suspended */
+       bool hpd_suspended : 1;
+       /* Set when a hotplug was received while HPD processing was
+        * suspended
+        */
+       bool hpd_waiting : 1;
+
+       /* Protects hpd_suspended */
+       struct mutex hpd_lock;
 };
 
 struct intel_encoder {
index fb5bb5b..4ee16b2 100644 (file)
@@ -336,8 +336,8 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
                                    bool *enabled, int width, int height)
 {
        struct drm_i915_private *dev_priv = to_i915(fb_helper->dev);
-       unsigned long conn_configured, conn_seq, mask;
        unsigned int count = min(fb_helper->connector_count, BITS_PER_LONG);
+       unsigned long conn_configured, conn_seq;
        int i, j;
        bool *save_enabled;
        bool fallback = true, ret = true;
@@ -355,10 +355,9 @@ static bool intel_fb_initial_config(struct drm_fb_helper *fb_helper,
                drm_modeset_backoff(&ctx);
 
        memcpy(save_enabled, enabled, count);
-       mask = GENMASK(count - 1, 0);
+       conn_seq = GENMASK(count - 1, 0);
        conn_configured = 0;
 retry:
-       conn_seq = conn_configured;
        for (i = 0; i < count; i++) {
                struct drm_fb_helper_connector *fb_conn;
                struct drm_connector *connector;
@@ -371,7 +370,8 @@ retry:
                if (conn_configured & BIT(i))
                        continue;
 
-               if (conn_seq == 0 && !connector->has_tile)
+               /* First pass, only consider tiled connectors */
+               if (conn_seq == GENMASK(count - 1, 0) && !connector->has_tile)
                        continue;
 
                if (connector->status == connector_status_connected)
@@ -475,8 +475,10 @@ retry:
                conn_configured |= BIT(i);
        }
 
-       if ((conn_configured & mask) != mask && conn_configured != conn_seq)
+       if (conn_configured != conn_seq) { /* repeat until no more are found */
+               conn_seq = conn_configured;
                goto retry;
+       }
 
        /*
         * If the BIOS didn't enable everything it could, fall back to have the
@@ -679,6 +681,7 @@ int intel_fbdev_init(struct drm_device *dev)
        if (ifbdev == NULL)
                return -ENOMEM;
 
+       mutex_init(&ifbdev->hpd_lock);
        drm_fb_helper_prepare(dev, &ifbdev->helper, &intel_fb_helper_funcs);
 
        if (!intel_fbdev_init_bios(dev, ifbdev))
@@ -752,6 +755,26 @@ void intel_fbdev_fini(struct drm_i915_private *dev_priv)
        intel_fbdev_destroy(ifbdev);
 }
 
+/* Suspends/resumes fbdev processing of incoming HPD events. When resuming HPD
+ * processing, fbdev will perform a full connector reprobe if a hotplug event
+ * was received while HPD was suspended.
+ */
+static void intel_fbdev_hpd_set_suspend(struct intel_fbdev *ifbdev, int state)
+{
+       bool send_hpd = false;
+
+       mutex_lock(&ifbdev->hpd_lock);
+       ifbdev->hpd_suspended = state == FBINFO_STATE_SUSPENDED;
+       send_hpd = !ifbdev->hpd_suspended && ifbdev->hpd_waiting;
+       ifbdev->hpd_waiting = false;
+       mutex_unlock(&ifbdev->hpd_lock);
+
+       if (send_hpd) {
+               DRM_DEBUG_KMS("Handling delayed fbcon HPD event\n");
+               drm_fb_helper_hotplug_event(&ifbdev->helper);
+       }
+}
+
 void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous)
 {
        struct drm_i915_private *dev_priv = to_i915(dev);
@@ -773,6 +796,7 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
                 */
                if (state != FBINFO_STATE_RUNNING)
                        flush_work(&dev_priv->fbdev_suspend_work);
+
                console_lock();
        } else {
                /*
@@ -800,17 +824,26 @@ void intel_fbdev_set_suspend(struct drm_device *dev, int state, bool synchronous
 
        drm_fb_helper_set_suspend(&ifbdev->helper, state);
        console_unlock();
+
+       intel_fbdev_hpd_set_suspend(ifbdev, state);
 }
 
 void intel_fbdev_output_poll_changed(struct drm_device *dev)
 {
        struct intel_fbdev *ifbdev = to_i915(dev)->fbdev;
+       bool send_hpd;
 
        if (!ifbdev)
                return;
 
        intel_fbdev_sync(ifbdev);
-       if (ifbdev->vma || ifbdev->helper.deferred_setup)
+
+       mutex_lock(&ifbdev->hpd_lock);
+       send_hpd = !ifbdev->hpd_suspended;
+       ifbdev->hpd_waiting = true;
+       mutex_unlock(&ifbdev->hpd_lock);
+
+       if (send_hpd && (ifbdev->vma || ifbdev->helper.deferred_setup))
                drm_fb_helper_hotplug_event(&ifbdev->helper);
 }
 
index 4be167d..eab9341 100644 (file)
@@ -303,6 +303,7 @@ static void __unwind_incomplete_requests(struct intel_engine_cs *engine)
         */
        if (!(prio & I915_PRIORITY_NEWCLIENT)) {
                prio |= I915_PRIORITY_NEWCLIENT;
+               active->sched.attr.priority = prio;
                list_move_tail(&active->sched.link,
                               i915_sched_lookup_priolist(engine, prio));
        }
@@ -645,6 +646,9 @@ static void execlists_dequeue(struct intel_engine_cs *engine)
                int i;
 
                priolist_for_each_request_consume(rq, rn, p, i) {
+                       GEM_BUG_ON(last &&
+                                  need_preempt(engine, last, rq_prio(rq)));
+
                        /*
                         * Can we combine this request with the current port?
                         * It has to be the same context/ringbuffer and not
@@ -2244,6 +2248,8 @@ static int logical_ring_init(struct intel_engine_cs *engine)
        if (ret)
                return ret;
 
+       intel_engine_init_workarounds(engine);
+
        if (HAS_LOGICAL_RING_ELSQ(i915)) {
                execlists->submit_reg = i915->regs +
                        i915_mmio_reg_offset(RING_EXECLIST_SQ_CONTENTS(engine));
@@ -2310,7 +2316,6 @@ int logical_render_ring_init(struct intel_engine_cs *engine)
        }
 
        intel_engine_init_whitelist(engine);
-       intel_engine_init_workarounds(engine);
 
        return 0;
 }
index b8f106d..3ac2015 100644 (file)
 struct opregion_header {
        u8 signature[16];
        u32 size;
-       u32 opregion_ver;
+       struct {
+               u8 rsvd;
+               u8 revision;
+               u8 minor;
+               u8 major;
+       }  __packed over;
        u8 bios_ver[32];
        u8 vbios_ver[16];
        u8 driver_ver[16];
@@ -119,7 +124,8 @@ struct opregion_asle {
        u64 fdss;
        u32 fdsp;
        u32 stat;
-       u64 rvda;       /* Physical address of raw vbt data */
+       u64 rvda;       /* Physical (2.0) or relative from opregion (2.1+)
+                        * address of raw VBT data. */
        u32 rvds;       /* Size of raw vbt data */
        u8 rsvd[58];
 } __packed;
@@ -925,6 +931,11 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
        opregion->header = base;
        opregion->lid_state = base + ACPI_CLID;
 
+       DRM_DEBUG_DRIVER("ACPI OpRegion version %u.%u.%u\n",
+                        opregion->header->over.major,
+                        opregion->header->over.minor,
+                        opregion->header->over.revision);
+
        mboxes = opregion->header->mboxes;
        if (mboxes & MBOX_ACPI) {
                DRM_DEBUG_DRIVER("Public ACPI methods supported\n");
@@ -953,11 +964,26 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
        if (dmi_check_system(intel_no_opregion_vbt))
                goto out;
 
-       if (opregion->header->opregion_ver >= 2 && opregion->asle &&
+       if (opregion->header->over.major >= 2 && opregion->asle &&
            opregion->asle->rvda && opregion->asle->rvds) {
-               opregion->rvda = memremap(opregion->asle->rvda,
-                                         opregion->asle->rvds,
+               resource_size_t rvda = opregion->asle->rvda;
+
+               /*
+                * opregion 2.0: rvda is the physical VBT address.
+                *
+                * opregion 2.1+: rvda is unsigned, relative offset from
+                * opregion base, and should never point within opregion.
+                */
+               if (opregion->header->over.major > 2 ||
+                   opregion->header->over.minor >= 1) {
+                       WARN_ON(rvda < OPREGION_SIZE);
+
+                       rvda += asls;
+               }
+
+               opregion->rvda = memremap(rvda, opregion->asle->rvds,
                                          MEMREMAP_WB);
+
                vbt = opregion->rvda;
                vbt_size = opregion->asle->rvds;
                if (intel_bios_is_valid_vbt(vbt, vbt_size)) {
@@ -967,6 +993,8 @@ int intel_opregion_setup(struct drm_i915_private *dev_priv)
                        goto out;
                } else {
                        DRM_DEBUG_KMS("Invalid VBT in ACPI OpRegion (RVDA)\n");
+                       memunmap(opregion->rvda);
+                       opregion->rvda = NULL;
                }
        }
 
index 419e563..f71970d 100644 (file)
@@ -274,10 +274,16 @@ void intel_psr_init_dpcd(struct intel_dp *intel_dp)
        DRM_DEBUG_KMS("eDP panel supports PSR version %x\n",
                      intel_dp->psr_dpcd[0]);
 
+       if (drm_dp_has_quirk(&intel_dp->desc, DP_DPCD_QUIRK_NO_PSR)) {
+               DRM_DEBUG_KMS("PSR support not currently available for this panel\n");
+               return;
+       }
+
        if (!(intel_dp->edp_dpcd[1] & DP_EDP_SET_POWER_CAP)) {
                DRM_DEBUG_KMS("Panel lacks power state control, PSR cannot be enabled\n");
                return;
        }
+
        dev_priv->psr.sink_support = true;
        dev_priv->psr.sink_sync_latency =
                intel_dp_get_sink_sync_latency(intel_dp);
index 72edaa7..a1a7cc2 100644 (file)
@@ -415,16 +415,17 @@ struct intel_engine_cs {
                /**
                 * @enable_count: Reference count for the enabled samplers.
                 *
-                * Index number corresponds to the bit number from @enable.
+                * Index number corresponds to @enum drm_i915_pmu_engine_sample.
                 */
-               unsigned int enable_count[I915_PMU_SAMPLE_BITS];
+               unsigned int enable_count[I915_ENGINE_SAMPLE_COUNT];
                /**
                 * @sample: Counter values for sampling events.
                 *
                 * Our internal timer stores the current counters in this field.
+                *
+                * Index number corresponds to @enum drm_i915_pmu_engine_sample.
                 */
-#define I915_ENGINE_SAMPLE_MAX (I915_SAMPLE_SEMA + 1)
-               struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_MAX];
+               struct i915_pmu_sample sample[I915_ENGINE_SAMPLE_COUNT];
        } pmu;
 
        /*
index d2e003d..5170a0f 100644 (file)
@@ -494,7 +494,7 @@ skl_program_plane(struct intel_plane *plane,
 
        keymax = (key->max_value & 0xffffff) | PLANE_KEYMAX_ALPHA(alpha);
 
-       keymsk = key->channel_mask & 0x3ffffff;
+       keymsk = key->channel_mask & 0x7ffffff;
        if (alpha < 0xff)
                keymsk |= PLANE_KEYMSK_ALPHA_ENABLE;
 
index 2c5bbe3..e31e263 100644 (file)
@@ -643,8 +643,10 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
                int bus_format;
 
                ret = of_property_read_u32(child, "reg", &i);
-               if (ret || i < 0 || i > 1)
-                       return -EINVAL;
+               if (ret || i < 0 || i > 1) {
+                       ret = -EINVAL;
+                       goto free_child;
+               }
 
                if (!of_device_is_available(child))
                        continue;
@@ -657,7 +659,6 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
                channel = &imx_ldb->channel[i];
                channel->ldb = imx_ldb;
                channel->chno = i;
-               channel->child = child;
 
                /*
                 * The output port is port@4 with an external 4-port mux or
@@ -667,13 +668,13 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
                                                  imx_ldb->lvds_mux ? 4 : 2, 0,
                                                  &channel->panel, &channel->bridge);
                if (ret && ret != -ENODEV)
-                       return ret;
+                       goto free_child;
 
                /* panel ddc only if there is no bridge */
                if (!channel->bridge) {
                        ret = imx_ldb_panel_ddc(dev, channel, child);
                        if (ret)
-                               return ret;
+                               goto free_child;
                }
 
                bus_format = of_get_bus_format(dev, child);
@@ -689,18 +690,26 @@ static int imx_ldb_bind(struct device *dev, struct device *master, void *data)
                if (bus_format < 0) {
                        dev_err(dev, "could not determine data mapping: %d\n",
                                bus_format);
-                       return bus_format;
+                       ret = bus_format;
+                       goto free_child;
                }
                channel->bus_format = bus_format;
+               channel->child = child;
 
                ret = imx_ldb_register(drm, channel);
-               if (ret)
-                       return ret;
+               if (ret) {
+                       channel->child = NULL;
+                       goto free_child;
+               }
        }
 
        dev_set_drvdata(dev, imx_ldb);
 
        return 0;
+
+free_child:
+       of_node_put(child);
+       return ret;
 }
 
 static void imx_ldb_unbind(struct device *dev, struct device *master,
index c390924..21e964f 100644 (file)
@@ -370,9 +370,9 @@ static int ipu_plane_atomic_check(struct drm_plane *plane,
        if (ret)
                return ret;
 
-       /* CRTC should be enabled */
+       /* nothing to check when disabling or disabled */
        if (!crtc_state->enable)
-               return -EINVAL;
+               return 0;
 
        switch (plane->type) {
        case DRM_PLANE_TYPE_PRIMARY:
index 75d97f1..4f5c67f 100644 (file)
@@ -46,7 +46,6 @@ struct meson_crtc {
        struct drm_crtc base;
        struct drm_pending_vblank_event *event;
        struct meson_drm *priv;
-       bool enabled;
 };
 #define to_meson_crtc(x) container_of(x, struct meson_crtc, base)
 
@@ -82,7 +81,8 @@ static const struct drm_crtc_funcs meson_crtc_funcs = {
 
 };
 
-static void meson_crtc_enable(struct drm_crtc *crtc)
+static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
+                                    struct drm_crtc_state *old_state)
 {
        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
        struct drm_crtc_state *crtc_state = crtc->state;
@@ -108,20 +108,6 @@ static void meson_crtc_enable(struct drm_crtc *crtc)
 
        drm_crtc_vblank_on(crtc);
 
-       meson_crtc->enabled = true;
-}
-
-static void meson_crtc_atomic_enable(struct drm_crtc *crtc,
-                                    struct drm_crtc_state *old_state)
-{
-       struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
-       struct meson_drm *priv = meson_crtc->priv;
-
-       DRM_DEBUG_DRIVER("\n");
-
-       if (!meson_crtc->enabled)
-               meson_crtc_enable(crtc);
-
        priv->viu.osd1_enabled = true;
 }
 
@@ -153,8 +139,6 @@ static void meson_crtc_atomic_disable(struct drm_crtc *crtc,
 
                crtc->state->event = NULL;
        }
-
-       meson_crtc->enabled = false;
 }
 
 static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
@@ -163,9 +147,6 @@ static void meson_crtc_atomic_begin(struct drm_crtc *crtc,
        struct meson_crtc *meson_crtc = to_meson_crtc(crtc);
        unsigned long flags;
 
-       if (crtc->state->enable && !meson_crtc->enabled)
-               meson_crtc_enable(crtc);
-
        if (crtc->state->event) {
                WARN_ON(drm_crtc_vblank_get(crtc) != 0);
 
index 3ee4d4a..12ff47b 100644 (file)
@@ -75,6 +75,10 @@ static const struct drm_mode_config_funcs meson_mode_config_funcs = {
        .fb_create           = drm_gem_fb_create,
 };
 
+static const struct drm_mode_config_helper_funcs meson_mode_config_helpers = {
+       .atomic_commit_tail = drm_atomic_helper_commit_tail_rpm,
+};
+
 static irqreturn_t meson_irq(int irq, void *arg)
 {
        struct drm_device *dev = arg;
@@ -266,6 +270,7 @@ static int meson_drv_bind_master(struct device *dev, bool has_components)
        drm->mode_config.max_width = 3840;
        drm->mode_config.max_height = 2160;
        drm->mode_config.funcs = &meson_mode_config_funcs;
+       drm->mode_config.helper_private = &meson_mode_config_helpers;
 
        /* Hardware Initialization */
 
@@ -388,8 +393,10 @@ static int meson_probe_remote(struct platform_device *pdev,
                remote_node = of_graph_get_remote_port_parent(ep);
                if (!remote_node ||
                    remote_node == parent || /* Ignore parent endpoint */
-                   !of_device_is_available(remote_node))
+                   !of_device_is_available(remote_node)) {
+                       of_node_put(remote_node);
                        continue;
+               }
 
                count += meson_probe_remote(pdev, match, remote, remote_node);
 
@@ -408,10 +415,13 @@ static int meson_drv_probe(struct platform_device *pdev)
 
        for_each_endpoint_of_node(np, ep) {
                remote = of_graph_get_remote_port_parent(ep);
-               if (!remote || !of_device_is_available(remote))
+               if (!remote || !of_device_is_available(remote)) {
+                       of_node_put(remote);
                        continue;
+               }
 
                count += meson_probe_remote(pdev, &match, np, remote);
+               of_node_put(remote);
        }
 
        if (count && !match)
index 5beb83d..ce1b3cc 100644 (file)
@@ -944,7 +944,7 @@ static u32 a6xx_gmu_get_arc_level(struct device *dev, unsigned long freq)
        np = dev_pm_opp_get_of_node(opp);
 
        if (np) {
-               of_property_read_u32(np, "qcom,level", &val);
+               of_property_read_u32(np, "opp-level", &val);
                of_node_put(np);
        }
 
index 2e4372e..2cfee1a 100644 (file)
@@ -765,7 +765,6 @@ int adreno_gpu_init(struct drm_device *drm, struct platform_device *pdev,
        adreno_gpu->rev = config->rev;
 
        adreno_gpu_config.ioname = "kgsl_3d0_reg_memory";
-       adreno_gpu_config.irqname = "kgsl_3d0_irq";
 
        adreno_gpu_config.va_start = SZ_16M;
        adreno_gpu_config.va_end = 0xffffffff;
index fd75870..6aefcd6 100644 (file)
@@ -365,19 +365,6 @@ static void _dpu_plane_set_qos_ctrl(struct drm_plane *plane,
                        &pdpu->pipe_qos_cfg);
 }
 
-static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
-{
-       struct dpu_plane *pdpu = to_dpu_plane(plane);
-       struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
-
-       if (!pdpu->is_rt_pipe)
-               return;
-
-       pm_runtime_get_sync(&dpu_kms->pdev->dev);
-       _dpu_plane_set_qos_ctrl(plane, enable, DPU_PLANE_QOS_PANIC_CTRL);
-       pm_runtime_put_sync(&dpu_kms->pdev->dev);
-}
-
 /**
  * _dpu_plane_set_ot_limit - set OT limit for the given plane
  * @plane:             Pointer to drm plane
@@ -1248,6 +1235,19 @@ static void dpu_plane_reset(struct drm_plane *plane)
 }
 
 #ifdef CONFIG_DEBUG_FS
+static void dpu_plane_danger_signal_ctrl(struct drm_plane *plane, bool enable)
+{
+       struct dpu_plane *pdpu = to_dpu_plane(plane);
+       struct dpu_kms *dpu_kms = _dpu_plane_get_kms(plane);
+
+       if (!pdpu->is_rt_pipe)
+               return;
+
+       pm_runtime_get_sync(&dpu_kms->pdev->dev);
+       _dpu_plane_set_qos_ctrl(plane, enable, DPU_PLANE_QOS_PANIC_CTRL);
+       pm_runtime_put_sync(&dpu_kms->pdev->dev);
+}
+
 static ssize_t _dpu_plane_danger_read(struct file *file,
                        char __user *buff, size_t count, loff_t *ppos)
 {
index 9cd6a96..927e5d8 100644 (file)
@@ -250,7 +250,8 @@ void msm_gem_purge_vma(struct msm_gem_address_space *aspace,
 void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
                struct msm_gem_vma *vma);
 int msm_gem_map_vma(struct msm_gem_address_space *aspace,
-               struct msm_gem_vma *vma, struct sg_table *sgt, int npages);
+               struct msm_gem_vma *vma, int prot,
+               struct sg_table *sgt, int npages);
 void msm_gem_close_vma(struct msm_gem_address_space *aspace,
                struct msm_gem_vma *vma);
 
@@ -333,6 +334,7 @@ void msm_gem_kernel_put(struct drm_gem_object *bo,
 struct drm_gem_object *msm_gem_import(struct drm_device *dev,
                struct dma_buf *dmabuf, struct sg_table *sgt);
 
+__printf(2, 3)
 void msm_gem_object_set_name(struct drm_gem_object *bo, const char *fmt, ...);
 
 int msm_framebuffer_prepare(struct drm_framebuffer *fb,
@@ -396,12 +398,14 @@ void msm_framebuffer_describe(struct drm_framebuffer *fb, struct seq_file *m);
 int msm_debugfs_late_init(struct drm_device *dev);
 int msm_rd_debugfs_init(struct drm_minor *minor);
 void msm_rd_debugfs_cleanup(struct msm_drm_private *priv);
+__printf(3, 4)
 void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,
                const char *fmt, ...);
 int msm_perf_debugfs_init(struct drm_minor *minor);
 void msm_perf_debugfs_cleanup(struct msm_drm_private *priv);
 #else
 static inline int msm_debugfs_late_init(struct drm_device *dev) { return 0; }
+__printf(3, 4)
 static inline void msm_rd_dump_submit(struct msm_rd_state *rd, struct msm_gem_submit *submit,
                const char *fmt, ...) {}
 static inline void msm_rd_debugfs_cleanup(struct msm_drm_private *priv) {}
index 51a95da..c8886d3 100644 (file)
@@ -391,6 +391,10 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj,
        struct msm_gem_object *msm_obj = to_msm_bo(obj);
        struct msm_gem_vma *vma;
        struct page **pages;
+       int prot = IOMMU_READ;
+
+       if (!(msm_obj->flags & MSM_BO_GPU_READONLY))
+               prot |= IOMMU_WRITE;
 
        WARN_ON(!mutex_is_locked(&msm_obj->lock));
 
@@ -405,8 +409,8 @@ static int msm_gem_pin_iova(struct drm_gem_object *obj,
        if (IS_ERR(pages))
                return PTR_ERR(pages);
 
-       return msm_gem_map_vma(aspace, vma, msm_obj->sgt,
-                       obj->size >> PAGE_SHIFT);
+       return msm_gem_map_vma(aspace, vma, prot,
+                       msm_obj->sgt, obj->size >> PAGE_SHIFT);
 }
 
 /* get iova and pin it. Should have a matching put */
index 5573607..49c0482 100644 (file)
@@ -68,7 +68,8 @@ void msm_gem_unmap_vma(struct msm_gem_address_space *aspace,
 
 int
 msm_gem_map_vma(struct msm_gem_address_space *aspace,
-               struct msm_gem_vma *vma, struct sg_table *sgt, int npages)
+               struct msm_gem_vma *vma, int prot,
+               struct sg_table *sgt, int npages)
 {
        unsigned size = npages << PAGE_SHIFT;
        int ret = 0;
@@ -86,7 +87,7 @@ msm_gem_map_vma(struct msm_gem_address_space *aspace,
 
        if (aspace->mmu)
                ret = aspace->mmu->funcs->map(aspace->mmu, vma->iova, sgt,
-                               size, IOMMU_READ | IOMMU_WRITE);
+                               size, prot);
 
        if (ret)
                vma->mapped = false;
index 5f3eff3..10babd1 100644 (file)
@@ -900,7 +900,7 @@ int msm_gpu_init(struct drm_device *drm, struct platform_device *pdev,
        }
 
        /* Get Interrupt: */
-       gpu->irq = platform_get_irq_byname(pdev, config->irqname);
+       gpu->irq = platform_get_irq(pdev, 0);
        if (gpu->irq < 0) {
                ret = gpu->irq;
                DRM_DEV_ERROR(drm->dev, "failed to get irq: %d\n", ret);
index efb49bb..ca17086 100644 (file)
@@ -31,7 +31,6 @@ struct msm_gpu_state;
 
 struct msm_gpu_config {
        const char *ioname;
-       const char *irqname;
        uint64_t va_start;
        uint64_t va_end;
        unsigned int nr_rings;
@@ -63,7 +62,7 @@ struct msm_gpu_funcs {
        struct msm_ringbuffer *(*active_ring)(struct msm_gpu *gpu);
        void (*recover)(struct msm_gpu *gpu);
        void (*destroy)(struct msm_gpu *gpu);
-#ifdef CONFIG_DEBUG_FS
+#if defined(CONFIG_DEBUG_FS) || defined(CONFIG_DEV_COREDUMP)
        /* show GPU status in debugfs: */
        void (*show)(struct msm_gpu *gpu, struct msm_gpu_state *state,
                        struct drm_printer *p);
index 90e9d0a..d211729 100644 (file)
@@ -115,7 +115,9 @@ static void rd_write(struct msm_rd_state *rd, const void *buf, int sz)
                char *fptr = &fifo->buf[fifo->head];
                int n;
 
-               wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0);
+               wait_event(rd->fifo_event, circ_space(&rd->fifo) > 0 || !rd->open);
+               if (!rd->open)
+                       return;
 
                /* Note that smp_load_acquire() is not strictly required
                 * as CIRC_SPACE_TO_END() does not access the tail more
@@ -213,7 +215,10 @@ out:
 static int rd_release(struct inode *inode, struct file *file)
 {
        struct msm_rd_state *rd = inode->i_private;
+
        rd->open = false;
+       wake_up_all(&rd->fifo_event);
+
        return 0;
 }
 
index 5f5be63..c7a94c9 100644 (file)
@@ -253,6 +253,9 @@ nouveau_backlight_init(struct drm_connector *connector)
        case NV_DEVICE_INFO_V0_FERMI:
        case NV_DEVICE_INFO_V0_KEPLER:
        case NV_DEVICE_INFO_V0_MAXWELL:
+       case NV_DEVICE_INFO_V0_PASCAL:
+       case NV_DEVICE_INFO_V0_VOLTA:
+       case NV_DEVICE_INFO_V0_TURING:
                ret = nv50_backlight_init(nv_encoder, &props, &ops);
                break;
        default:
index bfbc934..d9edb57 100644 (file)
@@ -2434,6 +2434,38 @@ nv140_chipset = {
        .sec2 = gp102_sec2_new,
 };
 
+static const struct nvkm_device_chip
+nv162_chipset = {
+       .name = "TU102",
+       .bar = tu104_bar_new,
+       .bios = nvkm_bios_new,
+       .bus = gf100_bus_new,
+       .devinit = tu104_devinit_new,
+       .fault = tu104_fault_new,
+       .fb = gv100_fb_new,
+       .fuse = gm107_fuse_new,
+       .gpio = gk104_gpio_new,
+       .i2c = gm200_i2c_new,
+       .ibus = gm200_ibus_new,
+       .imem = nv50_instmem_new,
+       .ltc = gp102_ltc_new,
+       .mc = tu104_mc_new,
+       .mmu = tu104_mmu_new,
+       .pci = gp100_pci_new,
+       .pmu = gp102_pmu_new,
+       .therm = gp100_therm_new,
+       .timer = gk20a_timer_new,
+       .top = gk104_top_new,
+       .ce[0] = tu104_ce_new,
+       .ce[1] = tu104_ce_new,
+       .ce[2] = tu104_ce_new,
+       .ce[3] = tu104_ce_new,
+       .ce[4] = tu104_ce_new,
+       .disp = tu104_disp_new,
+       .dma = gv100_dma_new,
+       .fifo = tu104_fifo_new,
+};
+
 static const struct nvkm_device_chip
 nv164_chipset = {
        .name = "TU104",
@@ -2950,6 +2982,7 @@ nvkm_device_ctor(const struct nvkm_device_func *func,
                case 0x138: device->chip = &nv138_chipset; break;
                case 0x13b: device->chip = &nv13b_chipset; break;
                case 0x140: device->chip = &nv140_chipset; break;
+               case 0x162: device->chip = &nv162_chipset; break;
                case 0x164: device->chip = &nv164_chipset; break;
                case 0x166: device->chip = &nv166_chipset; break;
                default:
index 816ccae..8675613 100644 (file)
@@ -22,6 +22,7 @@
 #include <engine/falcon.h>
 
 #include <core/gpuobj.h>
+#include <subdev/mc.h>
 #include <subdev/timer.h>
 #include <engine/fifo.h>
 
@@ -107,8 +108,10 @@ nvkm_falcon_fini(struct nvkm_engine *engine, bool suspend)
                }
        }
 
-       nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000);
-       nvkm_wr32(device, base + 0x014, 0xffffffff);
+       if (nvkm_mc_enabled(device, engine->subdev.index)) {
+               nvkm_mask(device, base + 0x048, 0x00000003, 0x00000000);
+               nvkm_wr32(device, base + 0x014, 0xffffffff);
+       }
        return 0;
 }
 
index 3695cde..07914e3 100644 (file)
@@ -132,11 +132,12 @@ nvkm_therm_update(struct nvkm_therm *therm, int mode)
                        duty = nvkm_therm_update_linear(therm);
                        break;
                case NVBIOS_THERM_FAN_OTHER:
-                       if (therm->cstate)
+                       if (therm->cstate) {
                                duty = therm->cstate;
-                       else
+                               poll = false;
+                       } else {
                                duty = nvkm_therm_update_linear_fallback(therm);
-                       poll = false;
+                       }
                        break;
                }
                immd = false;
index 00a9c2a..64fb788 100644 (file)
@@ -1406,7 +1406,7 @@ static void dsi_pll_disable(struct dss_pll *pll)
 
 static int dsi_dump_dsi_clocks(struct seq_file *s, void *p)
 {
-       struct dsi_data *dsi = p;
+       struct dsi_data *dsi = s->private;
        struct dss_pll_clock_info *cinfo = &dsi->pll.cinfo;
        enum dss_clk_source dispc_clk_src, dsi_clk_src;
        int dsi_module = dsi->module_id;
@@ -1467,7 +1467,7 @@ static int dsi_dump_dsi_clocks(struct seq_file *s, void *p)
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
 static int dsi_dump_dsi_irqs(struct seq_file *s, void *p)
 {
-       struct dsi_data *dsi = p;
+       struct dsi_data *dsi = s->private;
        unsigned long flags;
        struct dsi_irq_stats stats;
 
@@ -1558,7 +1558,7 @@ static int dsi_dump_dsi_irqs(struct seq_file *s, void *p)
 
 static int dsi_dump_dsi_regs(struct seq_file *s, void *p)
 {
-       struct dsi_data *dsi = p;
+       struct dsi_data *dsi = s->private;
 
        if (dsi_runtime_get(dsi))
                return 0;
@@ -4751,6 +4751,17 @@ static int dsi_set_config(struct omap_dss_device *dssdev,
        dsi->vm.flags |= DISPLAY_FLAGS_HSYNC_HIGH;
        dsi->vm.flags &= ~DISPLAY_FLAGS_VSYNC_LOW;
        dsi->vm.flags |= DISPLAY_FLAGS_VSYNC_HIGH;
+       /*
+        * HACK: These flags should be handled through the omap_dss_device bus
+        * flags, but this will only be possible when the DSI encoder will be
+        * converted to the omapdrm-managed encoder model.
+        */
+       dsi->vm.flags &= ~DISPLAY_FLAGS_PIXDATA_NEGEDGE;
+       dsi->vm.flags |= DISPLAY_FLAGS_PIXDATA_POSEDGE;
+       dsi->vm.flags &= ~DISPLAY_FLAGS_DE_LOW;
+       dsi->vm.flags |= DISPLAY_FLAGS_DE_HIGH;
+       dsi->vm.flags &= ~DISPLAY_FLAGS_SYNC_POSEDGE;
+       dsi->vm.flags |= DISPLAY_FLAGS_SYNC_NEGEDGE;
 
        dss_mgr_set_timings(&dsi->output, &dsi->vm);
 
@@ -5083,15 +5094,15 @@ static int dsi_bind(struct device *dev, struct device *master, void *data)
 
        snprintf(name, sizeof(name), "dsi%u_regs", dsi->module_id + 1);
        dsi->debugfs.regs = dss_debugfs_create_file(dss, name,
-                                                   dsi_dump_dsi_regs, &dsi);
+                                                   dsi_dump_dsi_regs, dsi);
 #ifdef CONFIG_OMAP2_DSS_COLLECT_IRQ_STATS
        snprintf(name, sizeof(name), "dsi%u_irqs", dsi->module_id + 1);
        dsi->debugfs.irqs = dss_debugfs_create_file(dss, name,
-                                                   dsi_dump_dsi_irqs, &dsi);
+                                                   dsi_dump_dsi_irqs, dsi);
 #endif
        snprintf(name, sizeof(name), "dsi%u_clks", dsi->module_id + 1);
        dsi->debugfs.clks = dss_debugfs_create_file(dss, name,
-                                                   dsi_dump_dsi_clocks, &dsi);
+                                                   dsi_dump_dsi_clocks, dsi);
 
        return 0;
 }
@@ -5104,8 +5115,6 @@ static void dsi_unbind(struct device *dev, struct device *master, void *data)
        dss_debugfs_remove_file(dsi->debugfs.irqs);
        dss_debugfs_remove_file(dsi->debugfs.regs);
 
-       of_platform_depopulate(dev);
-
        WARN_ON(dsi->scp_clk_refcount > 0);
 
        dss_pll_unregister(&dsi->pll);
@@ -5457,6 +5466,8 @@ static int dsi_remove(struct platform_device *pdev)
 
        dsi_uninit_output(dsi);
 
+       of_platform_depopulate(&pdev->dev);
+
        pm_runtime_disable(&pdev->dev);
 
        if (dsi->vdds_dsi_reg != NULL && dsi->vdds_dsi_enabled) {
index 13c8a66..ccb090f 100644 (file)
@@ -250,14 +250,10 @@ static struct drm_driver qxl_driver = {
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = qxl_debugfs_init,
 #endif
-       .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
-       .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_prime_export = drm_gem_prime_export,
        .gem_prime_import = drm_gem_prime_import,
        .gem_prime_pin = qxl_gem_prime_pin,
        .gem_prime_unpin = qxl_gem_prime_unpin,
-       .gem_prime_get_sg_table = qxl_gem_prime_get_sg_table,
-       .gem_prime_import_sg_table = qxl_gem_prime_import_sg_table,
        .gem_prime_vmap = qxl_gem_prime_vmap,
        .gem_prime_vunmap = qxl_gem_prime_vunmap,
        .gem_prime_mmap = qxl_gem_prime_mmap,
index a55dece..df65d3c 100644 (file)
@@ -38,20 +38,6 @@ void qxl_gem_prime_unpin(struct drm_gem_object *obj)
        WARN_ONCE(1, "not implemented");
 }
 
-struct sg_table *qxl_gem_prime_get_sg_table(struct drm_gem_object *obj)
-{
-       WARN_ONCE(1, "not implemented");
-       return ERR_PTR(-ENOSYS);
-}
-
-struct drm_gem_object *qxl_gem_prime_import_sg_table(
-       struct drm_device *dev, struct dma_buf_attachment *attach,
-       struct sg_table *table)
-{
-       WARN_ONCE(1, "not implemented");
-       return ERR_PTR(-ENOSYS);
-}
-
 void *qxl_gem_prime_vmap(struct drm_gem_object *obj)
 {
        WARN_ONCE(1, "not implemented");
index d587779..a97294a 100644 (file)
@@ -5676,7 +5676,7 @@ int ci_dpm_init(struct radeon_device *rdev)
        u16 data_offset, size;
        u8 frev, crev;
        struct ci_power_info *pi;
-       enum pci_bus_speed speed_cap;
+       enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN;
        struct pci_dev *root = rdev->pdev->bus->self;
        int ret;
 
@@ -5685,7 +5685,8 @@ int ci_dpm_init(struct radeon_device *rdev)
                return -ENOMEM;
        rdev->pm.dpm.priv = pi;
 
-       speed_cap = pcie_get_speed_cap(root);
+       if (!pci_is_root_bus(rdev->pdev->bus))
+               speed_cap = pcie_get_speed_cap(root);
        if (speed_cap == PCI_SPEED_UNKNOWN) {
                pi->sys_pcie_mask = 0;
        } else {
index dec1e08..6a8fb6f 100644 (file)
@@ -172,6 +172,7 @@ int radeon_driver_load_kms(struct drm_device *dev, unsigned long flags)
        }
 
        if (radeon_is_px(dev)) {
+               dev_pm_set_driver_flags(dev->dev, DPM_FLAG_NEVER_SKIP);
                pm_runtime_use_autosuspend(dev->dev);
                pm_runtime_set_autosuspend_delay(dev->dev, 5000);
                pm_runtime_set_active(dev->dev);
index 8fb60b3..0a785ef 100644 (file)
@@ -6899,7 +6899,7 @@ int si_dpm_init(struct radeon_device *rdev)
        struct ni_power_info *ni_pi;
        struct si_power_info *si_pi;
        struct atom_clock_dividers dividers;
-       enum pci_bus_speed speed_cap;
+       enum pci_bus_speed speed_cap = PCI_SPEED_UNKNOWN;
        struct pci_dev *root = rdev->pdev->bus->self;
        int ret;
 
@@ -6911,7 +6911,8 @@ int si_dpm_init(struct radeon_device *rdev)
        eg_pi = &ni_pi->eg;
        pi = &eg_pi->rv7xx;
 
-       speed_cap = pcie_get_speed_cap(root);
+       if (!pci_is_root_bus(rdev->pdev->bus))
+               speed_cap = pcie_get_speed_cap(root);
        if (speed_cap == PCI_SPEED_UNKNOWN) {
                si_pi->sys_pcie_mask = 0;
        } else {
index 96ac145..c0351ab 100644 (file)
@@ -1,17 +1,8 @@
-//SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
  * Author:
  *      Sandy Huang <hjc@rock-chips.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #include <drm/drmP.h>
@@ -113,8 +104,10 @@ struct rockchip_rgb *rockchip_rgb_init(struct device *dev,
                child_count++;
                ret = drm_of_find_panel_or_bridge(dev->of_node, 0, endpoint_id,
                                                  &panel, &bridge);
-               if (!ret)
+               if (!ret) {
+                       of_node_put(endpoint);
                        break;
+               }
        }
 
        of_node_put(port);
index 38b52e6..27b9635 100644 (file)
@@ -1,17 +1,8 @@
-//SPDX-License-Identifier: GPL-2.0+
+/* SPDX-License-Identifier: GPL-2.0 */
 /*
  * Copyright (C) Fuzhou Rockchip Electronics Co.Ltd
  * Author:
  *      Sandy Huang <hjc@rock-chips.com>
- *
- * This software is licensed under the terms of the GNU General Public
- * License version 2, as published by the Free Software Foundation, and
- * may be copied, distributed, and modified under those terms.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
  */
 
 #ifdef CONFIG_ROCKCHIP_RGB
index 4463d38..e2942c9 100644 (file)
@@ -440,13 +440,10 @@ struct drm_sched_job *drm_sched_entity_pop_job(struct drm_sched_entity *entity)
 
        while ((entity->dependency =
                        sched->ops->dependency(sched_job, entity))) {
+               trace_drm_sched_job_wait_dep(sched_job, entity->dependency);
 
-               if (drm_sched_entity_add_dependency_cb(entity)) {
-
-                       trace_drm_sched_job_wait_dep(sched_job,
-                                                    entity->dependency);
+               if (drm_sched_entity_add_dependency_cb(entity))
                        return NULL;
-               }
        }
 
        /* skip jobs from entity that marked guilty */
index 9e9255e..a021bab 100644 (file)
@@ -786,17 +786,18 @@ static struct sun4i_frontend *sun4i_backend_find_frontend(struct sun4i_drv *drv,
                remote = of_graph_get_remote_port_parent(ep);
                if (!remote)
                        continue;
+               of_node_put(remote);
 
                /* does this node match any registered engines? */
                list_for_each_entry(frontend, &drv->frontend_list, list) {
                        if (remote == frontend->node) {
-                               of_node_put(remote);
                                of_node_put(port);
+                               of_node_put(ep);
                                return frontend;
                        }
                }
        }
-
+       of_node_put(port);
        return ERR_PTR(-EINVAL);
 }
 
index 061d2e0..416da53 100644 (file)
@@ -92,6 +92,8 @@ static void sun4i_hdmi_disable(struct drm_encoder *encoder)
        val = readl(hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
        val &= ~SUN4I_HDMI_VID_CTRL_ENABLE;
        writel(val, hdmi->base + SUN4I_HDMI_VID_CTRL_REG);
+
+       clk_disable_unprepare(hdmi->tmds_clk);
 }
 
 static void sun4i_hdmi_enable(struct drm_encoder *encoder)
@@ -102,6 +104,8 @@ static void sun4i_hdmi_enable(struct drm_encoder *encoder)
 
        DRM_DEBUG_DRIVER("Enabling the HDMI Output\n");
 
+       clk_prepare_enable(hdmi->tmds_clk);
+
        sun4i_hdmi_setup_avi_infoframes(hdmi, mode);
        val |= SUN4I_HDMI_PKT_CTRL_TYPE(0, SUN4I_HDMI_PKT_AVI);
        val |= SUN4I_HDMI_PKT_CTRL_TYPE(1, SUN4I_HDMI_PKT_END);
index 0420f5c..cf45d0f 100644 (file)
@@ -761,6 +761,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
                        return PTR_ERR(tcon->sclk0);
                }
        }
+       clk_prepare_enable(tcon->sclk0);
 
        if (tcon->quirks->has_channel_1) {
                tcon->sclk1 = devm_clk_get(dev, "tcon-ch1");
@@ -775,6 +776,7 @@ static int sun4i_tcon_init_clocks(struct device *dev,
 
 static void sun4i_tcon_free_clocks(struct sun4i_tcon *tcon)
 {
+       clk_disable_unprepare(tcon->sclk0);
        clk_disable_unprepare(tcon->clk);
 }
 
index f7f32a8..2d1aaca 100644 (file)
@@ -127,14 +127,10 @@ static struct drm_driver driver = {
 #if defined(CONFIG_DEBUG_FS)
        .debugfs_init = virtio_gpu_debugfs_init,
 #endif
-       .prime_handle_to_fd = drm_gem_prime_handle_to_fd,
-       .prime_fd_to_handle = drm_gem_prime_fd_to_handle,
        .gem_prime_export = drm_gem_prime_export,
        .gem_prime_import = drm_gem_prime_import,
        .gem_prime_pin = virtgpu_gem_prime_pin,
        .gem_prime_unpin = virtgpu_gem_prime_unpin,
-       .gem_prime_get_sg_table = virtgpu_gem_prime_get_sg_table,
-       .gem_prime_import_sg_table = virtgpu_gem_prime_import_sg_table,
        .gem_prime_vmap = virtgpu_gem_prime_vmap,
        .gem_prime_vunmap = virtgpu_gem_prime_vunmap,
        .gem_prime_mmap = virtgpu_gem_prime_mmap,
index 1deb41d..0c15000 100644 (file)
@@ -372,10 +372,6 @@ int virtio_gpu_object_wait(struct virtio_gpu_object *bo, bool no_wait);
 /* virtgpu_prime.c */
 int virtgpu_gem_prime_pin(struct drm_gem_object *obj);
 void virtgpu_gem_prime_unpin(struct drm_gem_object *obj);
-struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj);
-struct drm_gem_object *virtgpu_gem_prime_import_sg_table(
-       struct drm_device *dev, struct dma_buf_attachment *attach,
-       struct sg_table *sgt);
 void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj);
 void virtgpu_gem_prime_vunmap(struct drm_gem_object *obj, void *vaddr);
 int virtgpu_gem_prime_mmap(struct drm_gem_object *obj,
index 86ce0ae..c59ec34 100644 (file)
@@ -39,20 +39,6 @@ void virtgpu_gem_prime_unpin(struct drm_gem_object *obj)
        WARN_ONCE(1, "not implemented");
 }
 
-struct sg_table *virtgpu_gem_prime_get_sg_table(struct drm_gem_object *obj)
-{
-       WARN_ONCE(1, "not implemented");
-       return ERR_PTR(-ENODEV);
-}
-
-struct drm_gem_object *virtgpu_gem_prime_import_sg_table(
-       struct drm_device *dev, struct dma_buf_attachment *attach,
-       struct sg_table *table)
-{
-       WARN_ONCE(1, "not implemented");
-       return ERR_PTR(-ENODEV);
-}
-
 void *virtgpu_gem_prime_vmap(struct drm_gem_object *obj)
 {
        struct virtio_gpu_object *bo = gem_to_virtio_gpu_obj(obj);
index 9d9e814..d7b409a 100644 (file)
@@ -1,4 +1,5 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
+
 #include "vkms_drv.h"
 #include <linux/crc32.h>
 #include <drm/drm_atomic.h>
index 177bbcb..eb56ee8 100644 (file)
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include "vkms_drv.h"
 #include <drm/drm_atomic_helper.h>
index 8308787..7dcbecb 100644 (file)
@@ -1,9 +1,4 @@
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 /**
  * DOC: vkms (Virtual Kernel Modesetting)
index e4469cd..81f1cfb 100644 (file)
@@ -1,3 +1,5 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+
 #ifndef _VKMS_DRV_H_
 #define _VKMS_DRV_H_
 
index 80311da..138b0bb 100644 (file)
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include <linux/shmem_fs.h>
 
index 271a0eb..4173e4f 100644 (file)
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include "vkms_drv.h"
 #include <drm/drm_crtc_helper.h>
index 4188176..0e67d2d 100644 (file)
@@ -1,10 +1,4 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- */
+// SPDX-License-Identifier: GPL-2.0+
 
 #include "vkms_drv.h"
 #include <drm/drm_plane_helper.h>
index 25afb1d..7ef5dcb 100644 (file)
@@ -26,6 +26,7 @@
  **************************************************************************/
 #include <linux/module.h>
 #include <linux/console.h>
+#include <linux/dma-mapping.h>
 
 #include <drm/drmP.h>
 #include "vmwgfx_drv.h"
@@ -34,7 +35,6 @@
 #include <drm/ttm/ttm_placement.h>
 #include <drm/ttm/ttm_bo_driver.h>
 #include <drm/ttm/ttm_module.h>
-#include <linux/intel-iommu.h>
 
 #define VMWGFX_DRIVER_DESC "Linux drm driver for VMware graphics devices"
 #define VMWGFX_CHIP_SVGAII 0
@@ -545,6 +545,21 @@ static void vmw_get_initial_size(struct vmw_private *dev_priv)
        dev_priv->initial_height = height;
 }
 
+/**
+ * vmw_assume_iommu - Figure out whether coherent dma-remapping might be
+ * taking place.
+ * @dev: Pointer to the struct drm_device.
+ *
+ * Return: true if iommu present, false otherwise.
+ */
+static bool vmw_assume_iommu(struct drm_device *dev)
+{
+       const struct dma_map_ops *ops = get_dma_ops(dev->dev);
+
+       return !dma_is_direct(ops) && ops &&
+               ops->map_page != dma_direct_map_page;
+}
+
 /**
  * vmw_dma_select_mode - Determine how DMA mappings should be set up for this
  * system.
@@ -565,55 +580,27 @@ static int vmw_dma_select_mode(struct vmw_private *dev_priv)
                [vmw_dma_alloc_coherent] = "Using coherent TTM pages.",
                [vmw_dma_map_populate] = "Keeping DMA mappings.",
                [vmw_dma_map_bind] = "Giving up DMA mappings early."};
-#ifdef CONFIG_X86
-       const struct dma_map_ops *dma_ops = get_dma_ops(dev_priv->dev->dev);
 
-#ifdef CONFIG_INTEL_IOMMU
-       if (intel_iommu_enabled) {
+       if (vmw_force_coherent)
+               dev_priv->map_mode = vmw_dma_alloc_coherent;
+       else if (vmw_assume_iommu(dev_priv->dev))
                dev_priv->map_mode = vmw_dma_map_populate;
-               goto out_fixup;
-       }
-#endif
-
-       if (!(vmw_force_iommu || vmw_force_coherent)) {
+       else if (!vmw_force_iommu)
                dev_priv->map_mode = vmw_dma_phys;
-               DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]);
-               return 0;
-       }
-
-       dev_priv->map_mode = vmw_dma_map_populate;
-
-       if (dma_ops && dma_ops->sync_single_for_cpu)
+       else if (IS_ENABLED(CONFIG_SWIOTLB) && swiotlb_nr_tbl())
                dev_priv->map_mode = vmw_dma_alloc_coherent;
-#ifdef CONFIG_SWIOTLB
-       if (swiotlb_nr_tbl() == 0)
+       else
                dev_priv->map_mode = vmw_dma_map_populate;
-#endif
 
-#ifdef CONFIG_INTEL_IOMMU
-out_fixup:
-#endif
-       if (dev_priv->map_mode == vmw_dma_map_populate &&
-           vmw_restrict_iommu)
+       if (dev_priv->map_mode == vmw_dma_map_populate && vmw_restrict_iommu)
                dev_priv->map_mode = vmw_dma_map_bind;
 
-       if (vmw_force_coherent)
-               dev_priv->map_mode = vmw_dma_alloc_coherent;
-
-#if !defined(CONFIG_SWIOTLB) && !defined(CONFIG_INTEL_IOMMU)
-       /*
-        * No coherent page pool
-        */
-       if (dev_priv->map_mode == vmw_dma_alloc_coherent)
+       /* No TTM coherent page pool? FIXME: Ask TTM instead! */
+        if (!(IS_ENABLED(CONFIG_SWIOTLB) || IS_ENABLED(CONFIG_INTEL_IOMMU)) &&
+           (dev_priv->map_mode == vmw_dma_alloc_coherent))
                return -EINVAL;
-#endif
-
-#else /* CONFIG_X86 */
-       dev_priv->map_mode = vmw_dma_map_populate;
-#endif /* CONFIG_X86 */
 
        DRM_INFO("DMA map mode: %s\n", names[dev_priv->map_mode]);
-
        return 0;
 }
 
@@ -625,24 +612,20 @@ out_fixup:
  * With 32-bit we can only handle 32 bit PFNs. Optionally set that
  * restriction also for 64-bit systems.
  */
-#ifdef CONFIG_INTEL_IOMMU
 static int vmw_dma_masks(struct vmw_private *dev_priv)
 {
        struct drm_device *dev = dev_priv->dev;
+       int ret = 0;
 
-       if (intel_iommu_enabled &&
+       ret = dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(64));
+       if (dev_priv->map_mode != vmw_dma_phys &&
            (sizeof(unsigned long) == 4 || vmw_restrict_dma_mask)) {
                DRM_INFO("Restricting DMA addresses to 44 bits.\n");
-               return dma_set_mask(dev->dev, DMA_BIT_MASK(44));
+               return dma_set_mask_and_coherent(dev->dev, DMA_BIT_MASK(44));
        }
-       return 0;
-}
-#else
-static int vmw_dma_masks(struct vmw_private *dev_priv)
-{
-       return 0;
+
+       return ret;
 }
-#endif
 
 static int vmw_driver_load(struct drm_device *dev, unsigned long chipset)
 {
index f2d13a7..88b8178 100644 (file)
@@ -3570,7 +3570,7 @@ int vmw_execbuf_fence_commands(struct drm_file *file_priv,
                *p_fence = NULL;
        }
 
-       return 0;
+       return ret;
 }
 
 /**
index b351fb5..ed2f678 100644 (file)
@@ -1646,7 +1646,7 @@ static int vmw_kms_check_topology(struct drm_device *dev,
                struct drm_connector_state *conn_state;
                struct vmw_connector_state *vmw_conn_state;
 
-               if (!du->pref_active) {
+               if (!du->pref_active && new_crtc_state->enable) {
                        ret = -EINVAL;
                        goto clean;
                }
@@ -2554,8 +2554,8 @@ void vmw_kms_helper_validation_finish(struct vmw_private *dev_priv,
                                      user_fence_rep)
 {
        struct vmw_fence_obj *fence = NULL;
-       uint32_t handle;
-       int ret;
+       uint32_t handle = 0;
+       int ret = 0;
 
        if (file_priv || user_fence_rep || vmw_validation_has_bos(ctx) ||
            out_fence)
index 474b00e..0a7d439 100644 (file)
@@ -898,8 +898,8 @@ static struct ipu_devtype ipu_type_imx51 = {
        .cpmem_ofs = 0x1f000000,
        .srm_ofs = 0x1f040000,
        .tpm_ofs = 0x1f060000,
-       .csi0_ofs = 0x1f030000,
-       .csi1_ofs = 0x1f038000,
+       .csi0_ofs = 0x1e030000,
+       .csi1_ofs = 0x1e038000,
        .ic_ofs = 0x1e020000,
        .disp0_ofs = 0x1e040000,
        .disp1_ofs = 0x1e048000,
@@ -914,8 +914,8 @@ static struct ipu_devtype ipu_type_imx53 = {
        .cpmem_ofs = 0x07000000,
        .srm_ofs = 0x07040000,
        .tpm_ofs = 0x07060000,
-       .csi0_ofs = 0x07030000,
-       .csi1_ofs = 0x07038000,
+       .csi0_ofs = 0x06030000,
+       .csi1_ofs = 0x06038000,
        .ic_ofs = 0x06020000,
        .disp0_ofs = 0x06040000,
        .disp1_ofs = 0x06048000,
index 2f8db9d..4a28f3f 100644 (file)
@@ -106,6 +106,7 @@ struct ipu_pre {
        void                    *buffer_virt;
        bool                    in_use;
        unsigned int            safe_window_end;
+       unsigned int            last_bufaddr;
 };
 
 static DEFINE_MUTEX(ipu_pre_list_mutex);
@@ -185,6 +186,7 @@ void ipu_pre_configure(struct ipu_pre *pre, unsigned int width,
 
        writel(bufaddr, pre->regs + IPU_PRE_CUR_BUF);
        writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
+       pre->last_bufaddr = bufaddr;
 
        val = IPU_PRE_PREF_ENG_CTRL_INPUT_PIXEL_FORMAT(0) |
              IPU_PRE_PREF_ENG_CTRL_INPUT_ACTIVE_BPP(active_bpp) |
@@ -242,7 +244,11 @@ void ipu_pre_update(struct ipu_pre *pre, unsigned int bufaddr)
        unsigned short current_yblock;
        u32 val;
 
+       if (bufaddr == pre->last_bufaddr)
+               return;
+
        writel(bufaddr, pre->regs + IPU_PRE_NEXT_BUF);
+       pre->last_bufaddr = bufaddr;
 
        do {
                if (time_after(jiffies, timeout)) {
index b677e5d..d5f1d8e 100644 (file)
@@ -21,6 +21,7 @@ config VGA_SWITCHEROO
        bool "Laptop Hybrid Graphics - GPU switching support"
        depends on X86
        depends on ACPI
+       depends on PCI
        select VGA_ARB
        help
          Many laptops released in 2008/9/10 have two GPUs with a multiplexer
index f41d5fe..9993b69 100644 (file)
@@ -125,6 +125,7 @@ static int open_collection(struct hid_parser *parser, unsigned type)
 {
        struct hid_collection *collection;
        unsigned usage;
+       int collection_index;
 
        usage = parser->local.usage[0];
 
@@ -167,13 +168,13 @@ static int open_collection(struct hid_parser *parser, unsigned type)
        parser->collection_stack[parser->collection_stack_ptr++] =
                parser->device->maxcollection;
 
-       collection = parser->device->collection +
-               parser->device->maxcollection++;
+       collection_index = parser->device->maxcollection++;
+       collection = parser->device->collection + collection_index;
        collection->type = type;
        collection->usage = usage;
        collection->level = parser->collection_stack_ptr - 1;
-       collection->parent = parser->active_collection;
-       parser->active_collection = collection;
+       collection->parent_idx = (collection->level == 0) ? -1 :
+               parser->collection_stack[collection->level - 1];
 
        if (type == HID_COLLECTION_APPLICATION)
                parser->device->maxapplication++;
@@ -192,8 +193,6 @@ static int close_collection(struct hid_parser *parser)
                return -EINVAL;
        }
        parser->collection_stack_ptr--;
-       if (parser->active_collection)
-               parser->active_collection = parser->active_collection->parent;
        return 0;
 }
 
@@ -1006,10 +1005,12 @@ static void hid_apply_multiplier_to_field(struct hid_device *hid,
                usage = &field->usage[i];
 
                collection = &hid->collection[usage->collection_index];
-               while (collection && collection != multiplier_collection)
-                       collection = collection->parent;
+               while (collection->parent_idx != -1 &&
+                      collection != multiplier_collection)
+                       collection = &hid->collection[collection->parent_idx];
 
-               if (collection || multiplier_collection == NULL)
+               if (collection->parent_idx != -1 ||
+                   multiplier_collection == NULL)
                        usage->resolution_multiplier = effective_multiplier;
 
        }
@@ -1044,9 +1045,9 @@ static void hid_apply_multiplier(struct hid_device *hid,
         * applicable fields later.
         */
        multiplier_collection = &hid->collection[multiplier->usage->collection_index];
-       while (multiplier_collection &&
+       while (multiplier_collection->parent_idx != -1 &&
               multiplier_collection->type != HID_COLLECTION_LOGICAL)
-               multiplier_collection = multiplier_collection->parent;
+               multiplier_collection = &hid->collection[multiplier_collection->parent_idx];
 
        effective_multiplier = hid_calculate_multiplier(hid, multiplier);
 
index c530476..ac9fda1 100644 (file)
@@ -30,6 +30,7 @@
 
 #include <linux/debugfs.h>
 #include <linux/seq_file.h>
+#include <linux/kfifo.h>
 #include <linux/sched/signal.h>
 #include <linux/export.h>
 #include <linux/slab.h>
@@ -661,17 +662,12 @@ EXPORT_SYMBOL_GPL(hid_dump_device);
 /* enqueue string to 'events' ring buffer */
 void hid_debug_event(struct hid_device *hdev, char *buf)
 {
-       unsigned i;
        struct hid_debug_list *list;
        unsigned long flags;
 
        spin_lock_irqsave(&hdev->debug_list_lock, flags);
-       list_for_each_entry(list, &hdev->debug_list, node) {
-               for (i = 0; buf[i]; i++)
-                       list->hid_debug_buf[(list->tail + i) % HID_DEBUG_BUFSIZE] =
-                               buf[i];
-               list->tail = (list->tail + i) % HID_DEBUG_BUFSIZE;
-        }
+       list_for_each_entry(list, &hdev->debug_list, node)
+               kfifo_in(&list->hid_debug_fifo, buf, strlen(buf));
        spin_unlock_irqrestore(&hdev->debug_list_lock, flags);
 
        wake_up_interruptible(&hdev->debug_wait);
@@ -722,8 +718,7 @@ void hid_dump_input(struct hid_device *hdev, struct hid_usage *usage, __s32 valu
        hid_debug_event(hdev, buf);
 
        kfree(buf);
-        wake_up_interruptible(&hdev->debug_wait);
-
+       wake_up_interruptible(&hdev->debug_wait);
 }
 EXPORT_SYMBOL_GPL(hid_dump_input);
 
@@ -1083,8 +1078,8 @@ static int hid_debug_events_open(struct inode *inode, struct file *file)
                goto out;
        }
 
-       if (!(list->hid_debug_buf = kzalloc(HID_DEBUG_BUFSIZE, GFP_KERNEL))) {
-               err = -ENOMEM;
+       err = kfifo_alloc(&list->hid_debug_fifo, HID_DEBUG_FIFOSIZE, GFP_KERNEL);
+       if (err) {
                kfree(list);
                goto out;
        }
@@ -1104,77 +1099,57 @@ static ssize_t hid_debug_events_read(struct file *file, char __user *buffer,
                size_t count, loff_t *ppos)
 {
        struct hid_debug_list *list = file->private_data;
-       int ret = 0, len;
+       int ret = 0, copied;
        DECLARE_WAITQUEUE(wait, current);
 
        mutex_lock(&list->read_mutex);
-       while (ret == 0) {
-               if (list->head == list->tail) {
-                       add_wait_queue(&list->hdev->debug_wait, &wait);
-                       set_current_state(TASK_INTERRUPTIBLE);
-
-                       while (list->head == list->tail) {
-                               if (file->f_flags & O_NONBLOCK) {
-                                       ret = -EAGAIN;
-                                       break;
-                               }
-                               if (signal_pending(current)) {
-                                       ret = -ERESTARTSYS;
-                                       break;
-                               }
+       if (kfifo_is_empty(&list->hid_debug_fifo)) {
+               add_wait_queue(&list->hdev->debug_wait, &wait);
+               set_current_state(TASK_INTERRUPTIBLE);
+
+               while (kfifo_is_empty(&list->hid_debug_fifo)) {
+                       if (file->f_flags & O_NONBLOCK) {
+                               ret = -EAGAIN;
+                               break;
+                       }
 
-                               if (!list->hdev || !list->hdev->debug) {
-                                       ret = -EIO;
-                                       set_current_state(TASK_RUNNING);
-                                       goto out;
-                               }
+                       if (signal_pending(current)) {
+                               ret = -ERESTARTSYS;
+                               break;
+                       }
 
-                               /* allow O_NONBLOCK from other threads */
-                               mutex_unlock(&list->read_mutex);
-                               schedule();
-                               mutex_lock(&list->read_mutex);
-                               set_current_state(TASK_INTERRUPTIBLE);
+                       /* if list->hdev is NULL we cannot remove_wait_queue().
+                        * if list->hdev->debug is 0 then hid_debug_unregister()
+                        * was already called and list->hdev is being destroyed.
+                        * if we add remove_wait_queue() here we can hit a race.
+                        */
+                       if (!list->hdev || !list->hdev->debug) {
+                               ret = -EIO;
+                               set_current_state(TASK_RUNNING);
+                               goto out;
                        }
 
-                       set_current_state(TASK_RUNNING);
-                       remove_wait_queue(&list->hdev->debug_wait, &wait);
+                       /* allow O_NONBLOCK from other threads */
+                       mutex_unlock(&list->read_mutex);
+                       schedule();
+                       mutex_lock(&list->read_mutex);
+                       set_current_state(TASK_INTERRUPTIBLE);
                }
 
-               if (ret)
-                       goto out;
+               __set_current_state(TASK_RUNNING);
+               remove_wait_queue(&list->hdev->debug_wait, &wait);
 
-               /* pass the ringbuffer contents to userspace */
-copy_rest:
-               if (list->tail == list->head)
+               if (ret)
                        goto out;
-               if (list->tail > list->head) {
-                       len = list->tail - list->head;
-                       if (len > count)
-                               len = count;
-
-                       if (copy_to_user(buffer + ret, &list->hid_debug_buf[list->head], len)) {
-                               ret = -EFAULT;
-                               goto out;
-                       }
-                       ret += len;
-                       list->head += len;
-               } else {
-                       len = HID_DEBUG_BUFSIZE - list->head;
-                       if (len > count)
-                               len = count;
-
-                       if (copy_to_user(buffer, &list->hid_debug_buf[list->head], len)) {
-                               ret = -EFAULT;
-                               goto out;
-                       }
-                       list->head = 0;
-                       ret += len;
-                       count -= len;
-                       if (count > 0)
-                               goto copy_rest;
-               }
-
        }
+
+       /* pass the fifo content to userspace, locking is not needed with only
+        * one concurrent reader and one concurrent writer
+        */
+       ret = kfifo_to_user(&list->hid_debug_fifo, buffer, count, &copied);
+       if (ret)
+               goto out;
+       ret = copied;
 out:
        mutex_unlock(&list->read_mutex);
        return ret;
@@ -1185,7 +1160,7 @@ static __poll_t hid_debug_events_poll(struct file *file, poll_table *wait)
        struct hid_debug_list *list = file->private_data;
 
        poll_wait(file, &list->hdev->debug_wait, wait);
-       if (list->head != list->tail)
+       if (!kfifo_is_empty(&list->hid_debug_fifo))
                return EPOLLIN | EPOLLRDNORM;
        if (!list->hdev->debug)
                return EPOLLERR | EPOLLHUP;
@@ -1200,7 +1175,7 @@ static int hid_debug_events_release(struct inode *inode, struct file *file)
        spin_lock_irqsave(&list->hdev->debug_list_lock, flags);
        list_del(&list->node);
        spin_unlock_irqrestore(&list->hdev->debug_list_lock, flags);
-       kfree(list->hid_debug_buf);
+       kfifo_free(&list->hid_debug_fifo);
        kfree(list);
 
        return 0;
@@ -1246,4 +1221,3 @@ void hid_debug_exit(void)
 {
        debugfs_remove_recursive(hid_debug_root);
 }
-
index 518fa76..24f846d 100644 (file)
 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_010A 0x010a
 #define USB_DEVICE_ID_GENERAL_TOUCH_WIN8_PIT_E100 0xe100
 
+#define I2C_VENDOR_ID_GOODIX           0x27c6
+#define I2C_DEVICE_ID_GOODIX_01F0      0x01f0
+
 #define USB_VENDOR_ID_GOODTOUCH                0x1aad
 #define USB_DEVICE_ID_GOODTOUCH_000f   0x000f
 
index 8555ce7..c5edfa9 100644 (file)
@@ -179,6 +179,8 @@ static const struct i2c_hid_quirks {
                I2C_HID_QUIRK_DELAY_AFTER_SLEEP },
        { USB_VENDOR_ID_LG, I2C_DEVICE_ID_LG_8001,
                I2C_HID_QUIRK_NO_RUNTIME_PM },
+       { I2C_VENDOR_ID_GOODIX, I2C_DEVICE_ID_GOODIX_01F0,
+               I2C_HID_QUIRK_NO_RUNTIME_PM },
        { 0, 0 }
 };
 
index ce0ba20..bea4c98 100644 (file)
@@ -701,19 +701,12 @@ static int vmbus_close_internal(struct vmbus_channel *channel)
 int vmbus_disconnect_ring(struct vmbus_channel *channel)
 {
        struct vmbus_channel *cur_channel, *tmp;
-       unsigned long flags;
-       LIST_HEAD(list);
        int ret;
 
        if (channel->primary_channel != NULL)
                return -EINVAL;
 
-       /* Snapshot the list of subchannels */
-       spin_lock_irqsave(&channel->lock, flags);
-       list_splice_init(&channel->sc_list, &list);
-       spin_unlock_irqrestore(&channel->lock, flags);
-
-       list_for_each_entry_safe(cur_channel, tmp, &list, sc_list) {
+       list_for_each_entry_safe(cur_channel, tmp, &channel->sc_list, sc_list) {
                if (cur_channel->rescind)
                        wait_for_completion(&cur_channel->rescind_event);
 
index 5301fef..7c6349a 100644 (file)
@@ -888,12 +888,14 @@ static unsigned long handle_pg_range(unsigned long pg_start,
                        pfn_cnt -= pgs_ol;
                        /*
                         * Check if the corresponding memory block is already
-                        * online by checking its last previously backed page.
-                        * In case it is we need to bring rest (which was not
-                        * backed previously) online too.
+                        * online. It is possible to observe struct pages still
+                        * being uninitialized here so check section instead.
+                        * In case the section is online we need to bring the
+                        * rest of pfns (which were not backed previously)
+                        * online too.
                         */
                        if (start_pfn > has->start_pfn &&
-                           !PageReserved(pfn_to_page(start_pfn - 1)))
+                           online_section_nr(pfn_to_section_nr(start_pfn)))
                                hv_bring_pgs_online(has, start_pfn, pgs_ol);
 
                }
index 64d0c85..1f1a55e 100644 (file)
@@ -164,26 +164,25 @@ hv_get_ringbuffer_availbytes(const struct hv_ring_buffer_info *rbi,
 }
 
 /* Get various debug metrics for the specified ring buffer. */
-void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
-                                struct hv_ring_buffer_debug_info *debug_info)
+int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
+                               struct hv_ring_buffer_debug_info *debug_info)
 {
        u32 bytes_avail_towrite;
        u32 bytes_avail_toread;
 
-       if (ring_info->ring_buffer) {
-               hv_get_ringbuffer_availbytes(ring_info,
-                                       &bytes_avail_toread,
-                                       &bytes_avail_towrite);
-
-               debug_info->bytes_avail_toread = bytes_avail_toread;
-               debug_info->bytes_avail_towrite = bytes_avail_towrite;
-               debug_info->current_read_index =
-                       ring_info->ring_buffer->read_index;
-               debug_info->current_write_index =
-                       ring_info->ring_buffer->write_index;
-               debug_info->current_interrupt_mask =
-                       ring_info->ring_buffer->interrupt_mask;
-       }
+       if (!ring_info->ring_buffer)
+               return -EINVAL;
+
+       hv_get_ringbuffer_availbytes(ring_info,
+                                    &bytes_avail_toread,
+                                    &bytes_avail_towrite);
+       debug_info->bytes_avail_toread = bytes_avail_toread;
+       debug_info->bytes_avail_towrite = bytes_avail_towrite;
+       debug_info->current_read_index = ring_info->ring_buffer->read_index;
+       debug_info->current_write_index = ring_info->ring_buffer->write_index;
+       debug_info->current_interrupt_mask
+               = ring_info->ring_buffer->interrupt_mask;
+       return 0;
 }
 EXPORT_SYMBOL_GPL(hv_ringbuffer_get_debuginfo);
 
index d0ff656..403fee0 100644 (file)
@@ -313,12 +313,16 @@ static ssize_t out_intr_mask_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info outbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+                                         &outbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", outbound.current_interrupt_mask);
 }
 static DEVICE_ATTR_RO(out_intr_mask);
@@ -328,12 +332,15 @@ static ssize_t out_read_index_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info outbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+                                         &outbound);
+       if (ret < 0)
+               return ret;
        return sprintf(buf, "%d\n", outbound.current_read_index);
 }
 static DEVICE_ATTR_RO(out_read_index);
@@ -344,12 +351,15 @@ static ssize_t out_write_index_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info outbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+                                         &outbound);
+       if (ret < 0)
+               return ret;
        return sprintf(buf, "%d\n", outbound.current_write_index);
 }
 static DEVICE_ATTR_RO(out_write_index);
@@ -360,12 +370,15 @@ static ssize_t out_read_bytes_avail_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info outbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+                                         &outbound);
+       if (ret < 0)
+               return ret;
        return sprintf(buf, "%d\n", outbound.bytes_avail_toread);
 }
 static DEVICE_ATTR_RO(out_read_bytes_avail);
@@ -376,12 +389,15 @@ static ssize_t out_write_bytes_avail_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info outbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound, &outbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->outbound,
+                                         &outbound);
+       if (ret < 0)
+               return ret;
        return sprintf(buf, "%d\n", outbound.bytes_avail_towrite);
 }
 static DEVICE_ATTR_RO(out_write_bytes_avail);
@@ -391,12 +407,15 @@ static ssize_t in_intr_mask_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info inbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", inbound.current_interrupt_mask);
 }
 static DEVICE_ATTR_RO(in_intr_mask);
@@ -406,12 +425,15 @@ static ssize_t in_read_index_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info inbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", inbound.current_read_index);
 }
 static DEVICE_ATTR_RO(in_read_index);
@@ -421,12 +443,15 @@ static ssize_t in_write_index_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info inbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", inbound.current_write_index);
 }
 static DEVICE_ATTR_RO(in_write_index);
@@ -437,12 +462,15 @@ static ssize_t in_read_bytes_avail_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info inbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", inbound.bytes_avail_toread);
 }
 static DEVICE_ATTR_RO(in_read_bytes_avail);
@@ -453,12 +481,15 @@ static ssize_t in_write_bytes_avail_show(struct device *dev,
 {
        struct hv_device *hv_dev = device_to_hv_device(dev);
        struct hv_ring_buffer_debug_info inbound;
+       int ret;
 
        if (!hv_dev->channel)
                return -ENODEV;
-       if (hv_dev->channel->state != CHANNEL_OPENED_STATE)
-               return -EINVAL;
-       hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+
+       ret = hv_ringbuffer_get_debuginfo(&hv_dev->channel->inbound, &inbound);
+       if (ret < 0)
+               return ret;
+
        return sprintf(buf, "%d\n", inbound.bytes_avail_towrite);
 }
 static DEVICE_ATTR_RO(in_write_bytes_avail);
index 0e30fa0..f9b8e3e 100644 (file)
@@ -393,8 +393,10 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
        }
 
        rv = lm80_read_value(client, LM80_REG_FANDIV);
-       if (rv < 0)
+       if (rv < 0) {
+               mutex_unlock(&data->update_lock);
                return rv;
+       }
        reg = (rv & ~(3 << (2 * (nr + 1))))
            | (data->fan_div[nr] << (2 * (nr + 1)));
        lm80_write_value(client, LM80_REG_FANDIV, reg);
index c304007..59ee01f 100644 (file)
@@ -44,8 +44,8 @@
  * nct6796d    14      7       7       2+6    0xd420 0xc1    0x5ca3
  * nct6797d    14      7       7       2+6    0xd450 0xc1    0x5ca3
  *                                           (0xd451)
- * nct6798d    14      7       7       2+6    0xd458 0xc1    0x5ca3
- *                                           (0xd459)
+ * nct6798d    14      7       7       2+6    0xd428 0xc1    0x5ca3
+ *                                           (0xd429)
  *
  * #temp lists the number of monitored temperature sources (first value) plus
  * the number of directly connectable temperature sensors (second value).
@@ -138,7 +138,7 @@ MODULE_PARM_DESC(fan_debounce, "Enable debouncing for fan RPM signal");
 #define SIO_NCT6795_ID         0xd350
 #define SIO_NCT6796_ID         0xd420
 #define SIO_NCT6797_ID         0xd450
-#define SIO_NCT6798_ID         0xd458
+#define SIO_NCT6798_ID         0xd428
 #define SIO_ID_MASK            0xFFF8
 
 enum pwm_enable { off, manual, thermal_cruise, speed_cruise, sf3, sf4 };
@@ -3594,7 +3594,8 @@ nct6775_check_fan_inputs(struct nct6775_data *data)
                        fan5pin |= cr1b & BIT(5);
                        fan5pin |= creb & BIT(5);
 
-                       fan6pin = creb & BIT(3);
+                       fan6pin = !dsw_en && (cr2d & BIT(1));
+                       fan6pin |= creb & BIT(3);
 
                        pwm5pin |= cr2d & BIT(7);
                        pwm5pin |= (creb & BIT(4)) && !(cr2a & BIT(0));
@@ -4508,7 +4509,8 @@ static int __maybe_unused nct6775_resume(struct device *dev)
 
        if (data->kind == nct6791 || data->kind == nct6792 ||
            data->kind == nct6793 || data->kind == nct6795 ||
-           data->kind == nct6796)
+           data->kind == nct6796 || data->kind == nct6797 ||
+           data->kind == nct6798)
                nct6791_enable_io_mapping(sioreg);
 
        superio_exit(sioreg);
@@ -4644,7 +4646,8 @@ static int __init nct6775_find(int sioaddr, struct nct6775_sio_data *sio_data)
 
        if (sio_data->kind == nct6791 || sio_data->kind == nct6792 ||
            sio_data->kind == nct6793 || sio_data->kind == nct6795 ||
-           sio_data->kind == nct6796)
+           sio_data->kind == nct6796 || sio_data->kind == nct6797 ||
+           sio_data->kind == nct6798)
                nct6791_enable_io_mapping(sioaddr);
 
        superio_exit(sioaddr);
index 423903f..391118c 100644 (file)
@@ -380,8 +380,8 @@ static ssize_t occ_show_power_1(struct device *dev,
                val *= 1000000ULL;
                break;
        case 2:
-               val = get_unaligned_be32(&power->update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 3:
                val = get_unaligned_be16(&power->value) * 1000000ULL;
@@ -425,8 +425,8 @@ static ssize_t occ_show_power_2(struct device *dev,
                                       &power->update_tag);
                break;
        case 2:
-               val = get_unaligned_be32(&power->update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 3:
                val = get_unaligned_be16(&power->value) * 1000000ULL;
@@ -463,8 +463,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                                       &power->system.update_tag);
                break;
        case 2:
-               val = get_unaligned_be32(&power->system.update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->system.update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 3:
                val = get_unaligned_be16(&power->system.value) * 1000000ULL;
@@ -477,8 +477,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                                       &power->proc.update_tag);
                break;
        case 6:
-               val = get_unaligned_be32(&power->proc.update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->proc.update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 7:
                val = get_unaligned_be16(&power->proc.value) * 1000000ULL;
@@ -491,8 +491,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                                       &power->vdd.update_tag);
                break;
        case 10:
-               val = get_unaligned_be32(&power->vdd.update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->vdd.update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 11:
                val = get_unaligned_be16(&power->vdd.value) * 1000000ULL;
@@ -505,8 +505,8 @@ static ssize_t occ_show_power_a0(struct device *dev,
                                       &power->vdn.update_tag);
                break;
        case 14:
-               val = get_unaligned_be32(&power->vdn.update_tag) *
-                       occ->powr_sample_time_us;
+               val = (u64)get_unaligned_be32(&power->vdn.update_tag) *
+                          occ->powr_sample_time_us;
                break;
        case 15:
                val = get_unaligned_be16(&power->vdn.value) * 1000000ULL;
index 8844c95..7053be5 100644 (file)
@@ -88,7 +88,7 @@ static const struct of_device_id tmp421_of_match[] = {
                .data = (void *)2
        },
        {
-               .compatible = "ti,tmp422",
+               .compatible = "ti,tmp442",
                .data = (void *)3
        },
        { },
index ec6e69a..d2fbb4b 100644 (file)
@@ -183,6 +183,15 @@ static void bcm2835_i2c_start_transfer(struct bcm2835_i2c_dev *i2c_dev)
        bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C, c);
 }
 
+static void bcm2835_i2c_finish_transfer(struct bcm2835_i2c_dev *i2c_dev)
+{
+       i2c_dev->curr_msg = NULL;
+       i2c_dev->num_msgs = 0;
+
+       i2c_dev->msg_buf = NULL;
+       i2c_dev->msg_buf_remaining = 0;
+}
+
 /*
  * Note about I2C_C_CLEAR on error:
  * The I2C_C_CLEAR on errors will take some time to resolve -- if you were in
@@ -283,6 +292,9 @@ static int bcm2835_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[],
 
        time_left = wait_for_completion_timeout(&i2c_dev->completion,
                                                adap->timeout);
+
+       bcm2835_i2c_finish_transfer(i2c_dev);
+
        if (!time_left) {
                bcm2835_i2c_writel(i2c_dev, BCM2835_I2C_C,
                                   BCM2835_I2C_C_CLEAR);
index b136057..d917cef 100644 (file)
@@ -382,8 +382,10 @@ static void cdns_i2c_mrecv(struct cdns_i2c *id)
         * Check for the message size against FIFO depth and set the
         * 'hold bus' bit if it is greater than FIFO depth.
         */
-       if (id->recv_count > CDNS_I2C_FIFO_DEPTH)
+       if ((id->recv_count > CDNS_I2C_FIFO_DEPTH)  || id->bus_hold_flag)
                ctrl_reg |= CDNS_I2C_CR_HOLD;
+       else
+               ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD;
 
        cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
 
@@ -440,8 +442,11 @@ static void cdns_i2c_msend(struct cdns_i2c *id)
         * Check for the message size against FIFO depth and set the
         * 'hold bus' bit if it is greater than FIFO depth.
         */
-       if (id->send_count > CDNS_I2C_FIFO_DEPTH)
+       if ((id->send_count > CDNS_I2C_FIFO_DEPTH) || id->bus_hold_flag)
                ctrl_reg |= CDNS_I2C_CR_HOLD;
+       else
+               ctrl_reg = ctrl_reg & ~CDNS_I2C_CR_HOLD;
+
        cdns_i2c_writereg(ctrl_reg, CDNS_I2C_CR_OFFSET);
 
        /* Clear the interrupts in interrupt status register. */
index b1086bf..cd9c65f 100644 (file)
@@ -1500,8 +1500,7 @@ static int omap_i2c_remove(struct platform_device *pdev)
        return 0;
 }
 
-#ifdef CONFIG_PM
-static int omap_i2c_runtime_suspend(struct device *dev)
+static int __maybe_unused omap_i2c_runtime_suspend(struct device *dev)
 {
        struct omap_i2c_dev *omap = dev_get_drvdata(dev);
 
@@ -1527,7 +1526,7 @@ static int omap_i2c_runtime_suspend(struct device *dev)
        return 0;
 }
 
-static int omap_i2c_runtime_resume(struct device *dev)
+static int __maybe_unused omap_i2c_runtime_resume(struct device *dev)
 {
        struct omap_i2c_dev *omap = dev_get_drvdata(dev);
 
@@ -1542,20 +1541,18 @@ static int omap_i2c_runtime_resume(struct device *dev)
 }
 
 static const struct dev_pm_ops omap_i2c_pm_ops = {
+       SET_NOIRQ_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend,
+                                     pm_runtime_force_resume)
        SET_RUNTIME_PM_OPS(omap_i2c_runtime_suspend,
                           omap_i2c_runtime_resume, NULL)
 };
-#define OMAP_I2C_PM_OPS (&omap_i2c_pm_ops)
-#else
-#define OMAP_I2C_PM_OPS NULL
-#endif /* CONFIG_PM */
 
 static struct platform_driver omap_i2c_driver = {
        .probe          = omap_i2c_probe,
        .remove         = omap_i2c_remove,
        .driver         = {
                .name   = "omap_i2c",
-               .pm     = OMAP_I2C_PM_OPS,
+               .pm     = &omap_i2c_pm_ops,
                .of_match_table = of_match_ptr(omap_i2c_of_match),
        },
 };
index e417ebf..c77adbb 100644 (file)
@@ -155,6 +155,8 @@ enum msg_end_type {
  * @has_mst_fifo: The I2C controller contains the new MST FIFO interface that
  *             provides additional features and allows for longer messages to
  *             be transferred in one go.
+ * @quirks: i2c adapter quirks for limiting write/read transfer size and not
+ *             allowing 0 length transfers.
  */
 struct tegra_i2c_hw_feature {
        bool has_continue_xfer_support;
@@ -167,6 +169,7 @@ struct tegra_i2c_hw_feature {
        bool has_multi_master_mode;
        bool has_slcg_override_reg;
        bool has_mst_fifo;
+       const struct i2c_adapter_quirks *quirks;
 };
 
 /**
@@ -837,6 +840,10 @@ static const struct i2c_adapter_quirks tegra_i2c_quirks = {
        .max_write_len = 4096,
 };
 
+static const struct i2c_adapter_quirks tegra194_i2c_quirks = {
+       .flags = I2C_AQ_NO_ZERO_LEN,
+};
+
 static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
        .has_continue_xfer_support = false,
        .has_per_pkt_xfer_complete_irq = false,
@@ -848,6 +855,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = {
        .has_multi_master_mode = false,
        .has_slcg_override_reg = false,
        .has_mst_fifo = false,
+       .quirks = &tegra_i2c_quirks,
 };
 
 static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
@@ -861,6 +869,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = {
        .has_multi_master_mode = false,
        .has_slcg_override_reg = false,
        .has_mst_fifo = false,
+       .quirks = &tegra_i2c_quirks,
 };
 
 static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
@@ -874,6 +883,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = {
        .has_multi_master_mode = false,
        .has_slcg_override_reg = false,
        .has_mst_fifo = false,
+       .quirks = &tegra_i2c_quirks,
 };
 
 static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
@@ -887,6 +897,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = {
        .has_multi_master_mode = false,
        .has_slcg_override_reg = true,
        .has_mst_fifo = false,
+       .quirks = &tegra_i2c_quirks,
 };
 
 static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
@@ -900,6 +911,7 @@ static const struct tegra_i2c_hw_feature tegra210_i2c_hw = {
        .has_multi_master_mode = true,
        .has_slcg_override_reg = true,
        .has_mst_fifo = false,
+       .quirks = &tegra_i2c_quirks,
 };
 
 static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
@@ -913,6 +925,7 @@ static const struct tegra_i2c_hw_feature tegra194_i2c_hw = {
        .has_multi_master_mode = true,
        .has_slcg_override_reg = true,
        .has_mst_fifo = true,
+       .quirks = &tegra194_i2c_quirks,
 };
 
 /* Match table for of_platform binding */
@@ -964,7 +977,6 @@ static int tegra_i2c_probe(struct platform_device *pdev)
        i2c_dev->base = base;
        i2c_dev->div_clk = div_clk;
        i2c_dev->adapter.algo = &tegra_i2c_algo;
-       i2c_dev->adapter.quirks = &tegra_i2c_quirks;
        i2c_dev->irq = irq;
        i2c_dev->cont_id = pdev->id;
        i2c_dev->dev = &pdev->dev;
@@ -980,6 +992,7 @@ static int tegra_i2c_probe(struct platform_device *pdev)
        i2c_dev->hw = of_device_get_match_data(&pdev->dev);
        i2c_dev->is_dvc = of_device_is_compatible(pdev->dev.of_node,
                                                  "nvidia,tegra20-i2c-dvc");
+       i2c_dev->adapter.quirks = i2c_dev->hw->quirks;
        init_completion(&i2c_dev->msg_complete);
        spin_lock_init(&i2c_dev->xfer_lock);
 
index 1aca742..ccd76c7 100644 (file)
@@ -470,9 +470,15 @@ static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
                                          data_arg.data);
        }
        case I2C_RETRIES:
+               if (arg > INT_MAX)
+                       return -EINVAL;
+
                client->adapter->retries = arg;
                break;
        case I2C_TIMEOUT:
+               if (arg > INT_MAX)
+                       return -EINVAL;
+
                /* For historical reasons, user-space sets the timeout
                 * value in units of 10 ms.
                 */
index c39f89d..2dc628d 100644 (file)
@@ -1828,7 +1828,7 @@ int i3c_master_add_i3c_dev_locked(struct i3c_master_controller *master,
 
        ret = i3c_master_retrieve_dev_info(newdev);
        if (ret)
-               goto err_free_dev;
+               goto err_detach_dev;
 
        olddev = i3c_master_search_i3c_dev_duplicate(newdev);
        if (olddev) {
index b532e2c..bb03079 100644 (file)
@@ -419,12 +419,9 @@ static void dw_i3c_master_enqueue_xfer(struct dw_i3c_master *master,
        spin_unlock_irqrestore(&master->xferqueue.lock, flags);
 }
 
-static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master,
-                                      struct dw_i3c_xfer *xfer)
+static void dw_i3c_master_dequeue_xfer_locked(struct dw_i3c_master *master,
+                                             struct dw_i3c_xfer *xfer)
 {
-       unsigned long flags;
-
-       spin_lock_irqsave(&master->xferqueue.lock, flags);
        if (master->xferqueue.cur == xfer) {
                u32 status;
 
@@ -439,6 +436,15 @@ static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master,
        } else {
                list_del_init(&xfer->node);
        }
+}
+
+static void dw_i3c_master_dequeue_xfer(struct dw_i3c_master *master,
+                                      struct dw_i3c_xfer *xfer)
+{
+       unsigned long flags;
+
+       spin_lock_irqsave(&master->xferqueue.lock, flags);
+       dw_i3c_master_dequeue_xfer_locked(master, xfer);
        spin_unlock_irqrestore(&master->xferqueue.lock, flags);
 }
 
@@ -494,7 +500,7 @@ static void dw_i3c_master_end_xfer_locked(struct dw_i3c_master *master, u32 isr)
        complete(&xfer->comp);
 
        if (ret < 0) {
-               dw_i3c_master_dequeue_xfer(master, xfer);
+               dw_i3c_master_dequeue_xfer_locked(master, xfer);
                writel(readl(master->regs + DEVICE_CTRL) | DEV_CTRL_RESUME,
                       master->regs + DEVICE_CTRL);
        }
@@ -901,9 +907,6 @@ static int dw_i3c_master_reattach_i3c_dev(struct i3c_dev_desc *dev,
               master->regs +
               DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
 
-       if (!old_dyn_addr)
-               return 0;
-
        master->addrs[data->index] = dev->info.dyn_addr;
 
        return 0;
@@ -925,11 +928,11 @@ static int dw_i3c_master_attach_i3c_dev(struct i3c_dev_desc *dev)
                return -ENOMEM;
 
        data->index = pos;
-       master->addrs[pos] = dev->info.dyn_addr;
+       master->addrs[pos] = dev->info.dyn_addr ? : dev->info.static_addr;
        master->free_pos &= ~BIT(pos);
        i3c_dev_set_master_data(dev, data);
 
-       writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(dev->info.dyn_addr),
+       writel(DEV_ADDR_TABLE_DYNAMIC_ADDR(master->addrs[pos]),
               master->regs +
               DEV_ADDR_TABLE_LOC(master->datstartaddr, data->index));
 
index bbd79b8..8889a4f 100644 (file)
@@ -1556,8 +1556,8 @@ static int cdns_i3c_master_probe(struct platform_device *pdev)
                return PTR_ERR(master->pclk);
 
        master->sysclk = devm_clk_get(&pdev->dev, "sysclk");
-       if (IS_ERR(master->pclk))
-               return PTR_ERR(master->pclk);
+       if (IS_ERR(master->sysclk))
+               return PTR_ERR(master->sysclk);
 
        irq = platform_get_irq(pdev, 0);
        if (irq < 0)
index da58020..33a28cd 100644 (file)
@@ -235,21 +235,28 @@ EXPORT_SYMBOL_GPL(ide_prep_sense);
 
 int ide_queue_sense_rq(ide_drive_t *drive, void *special)
 {
-       struct request *sense_rq = drive->sense_rq;
+       ide_hwif_t *hwif = drive->hwif;
+       struct request *sense_rq;
+       unsigned long flags;
+
+       spin_lock_irqsave(&hwif->lock, flags);
 
        /* deferred failure from ide_prep_sense() */
        if (!drive->sense_rq_armed) {
                printk(KERN_WARNING PFX "%s: error queuing a sense request\n",
                       drive->name);
+               spin_unlock_irqrestore(&hwif->lock, flags);
                return -ENOMEM;
        }
 
+       sense_rq = drive->sense_rq;
        ide_req(sense_rq)->special = special;
        drive->sense_rq_armed = false;
 
        drive->hwif->rq = NULL;
 
        ide_insert_request_head(drive, sense_rq);
+       spin_unlock_irqrestore(&hwif->lock, flags);
        return 0;
 }
 EXPORT_SYMBOL_GPL(ide_queue_sense_rq);
index 8445b48..b137f27 100644 (file)
@@ -68,8 +68,10 @@ int ide_end_rq(ide_drive_t *drive, struct request *rq, blk_status_t error,
        }
 
        if (!blk_update_request(rq, error, nr_bytes)) {
-               if (rq == drive->sense_rq)
+               if (rq == drive->sense_rq) {
                        drive->sense_rq = NULL;
+                       drive->sense_rq_active = false;
+               }
 
                __blk_mq_end_request(rq, error);
                return 0;
@@ -451,16 +453,11 @@ void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq)
                blk_mq_delay_run_hw_queue(q->queue_hw_ctx[0], 3);
 }
 
-/*
- * Issue a new request to a device.
- */
-blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
-                         const struct blk_mq_queue_data *bd)
+blk_status_t ide_issue_rq(ide_drive_t *drive, struct request *rq,
+                         bool local_requeue)
 {
-       ide_drive_t     *drive = hctx->queue->queuedata;
-       ide_hwif_t      *hwif = drive->hwif;
+       ide_hwif_t *hwif = drive->hwif;
        struct ide_host *host = hwif->host;
-       struct request  *rq = bd->rq;
        ide_startstop_t startstop;
 
        if (!blk_rq_is_passthrough(rq) && !(rq->rq_flags & RQF_DONTPREP)) {
@@ -474,8 +471,6 @@ blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
        if (ide_lock_host(host, hwif))
                return BLK_STS_DEV_RESOURCE;
 
-       blk_mq_start_request(rq);
-
        spin_lock_irq(&hwif->lock);
 
        if (!ide_lock_port(hwif)) {
@@ -510,18 +505,6 @@ repeat:
                hwif->cur_dev = drive;
                drive->dev_flags &= ~(IDE_DFLAG_SLEEPING | IDE_DFLAG_PARKED);
 
-               /*
-                * we know that the queue isn't empty, but this can happen
-                * if ->prep_rq() decides to kill a request
-                */
-               if (!rq) {
-                       rq = bd->rq;
-                       if (!rq) {
-                               ide_unlock_port(hwif);
-                               goto out;
-                       }
-               }
-
                /*
                 * Sanity: don't accept a request that isn't a PM request
                 * if we are currently power managed. This is very important as
@@ -560,9 +543,12 @@ repeat:
                }
        } else {
 plug_device:
+               if (local_requeue)
+                       list_add(&rq->queuelist, &drive->rq_list);
                spin_unlock_irq(&hwif->lock);
                ide_unlock_host(host);
-               ide_requeue_and_plug(drive, rq);
+               if (!local_requeue)
+                       ide_requeue_and_plug(drive, rq);
                return BLK_STS_OK;
        }
 
@@ -573,6 +559,26 @@ out:
        return BLK_STS_OK;
 }
 
+/*
+ * Issue a new request to a device.
+ */
+blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *hctx,
+                         const struct blk_mq_queue_data *bd)
+{
+       ide_drive_t *drive = hctx->queue->queuedata;
+       ide_hwif_t *hwif = drive->hwif;
+
+       spin_lock_irq(&hwif->lock);
+       if (drive->sense_rq_active) {
+               spin_unlock_irq(&hwif->lock);
+               return BLK_STS_DEV_RESOURCE;
+       }
+       spin_unlock_irq(&hwif->lock);
+
+       blk_mq_start_request(bd->rq);
+       return ide_issue_rq(drive, bd->rq, false);
+}
+
 static int drive_is_ready(ide_drive_t *drive)
 {
        ide_hwif_t *hwif = drive->hwif;
@@ -893,13 +899,8 @@ EXPORT_SYMBOL_GPL(ide_pad_transfer);
 
 void ide_insert_request_head(ide_drive_t *drive, struct request *rq)
 {
-       ide_hwif_t *hwif = drive->hwif;
-       unsigned long flags;
-
-       spin_lock_irqsave(&hwif->lock, flags);
+       drive->sense_rq_active = true;
        list_add_tail(&rq->queuelist, &drive->rq_list);
-       spin_unlock_irqrestore(&hwif->lock, flags);
-
        kblockd_schedule_work(&drive->rq_work);
 }
 EXPORT_SYMBOL_GPL(ide_insert_request_head);
index 102aa3b..8af7af6 100644 (file)
@@ -54,7 +54,9 @@ static void issue_park_cmd(ide_drive_t *drive, unsigned long timeout)
        scsi_req(rq)->cmd[0] = REQ_UNPARK_HEADS;
        scsi_req(rq)->cmd_len = 1;
        ide_req(rq)->type = ATA_PRIV_MISC;
+       spin_lock_irq(&hwif->lock);
        ide_insert_request_head(drive, rq);
+       spin_unlock_irq(&hwif->lock);
 
 out:
        return;
index 63627be..5aeaca2 100644 (file)
@@ -1159,18 +1159,27 @@ static void drive_rq_insert_work(struct work_struct *work)
        ide_drive_t *drive = container_of(work, ide_drive_t, rq_work);
        ide_hwif_t *hwif = drive->hwif;
        struct request *rq;
+       blk_status_t ret;
        LIST_HEAD(list);
 
-       spin_lock_irq(&hwif->lock);
-       if (!list_empty(&drive->rq_list))
-               list_splice_init(&drive->rq_list, &list);
-       spin_unlock_irq(&hwif->lock);
+       blk_mq_quiesce_queue(drive->queue);
 
-       while (!list_empty(&list)) {
-               rq = list_first_entry(&list, struct request, queuelist);
+       ret = BLK_STS_OK;
+       spin_lock_irq(&hwif->lock);
+       while (!list_empty(&drive->rq_list)) {
+               rq = list_first_entry(&drive->rq_list, struct request, queuelist);
                list_del_init(&rq->queuelist);
-               blk_execute_rq_nowait(drive->queue, rq->rq_disk, rq, true, NULL);
+
+               spin_unlock_irq(&hwif->lock);
+               ret = ide_issue_rq(drive, rq, true);
+               spin_lock_irq(&hwif->lock);
        }
+       spin_unlock_irq(&hwif->lock);
+
+       blk_mq_unquiesce_queue(drive->queue);
+
+       if (ret != BLK_STS_OK)
+               kblockd_schedule_work(&drive->rq_work);
 }
 
 static const u8 ide_hwif_to_major[] =
index 4c8c7a6..a5dc135 100644 (file)
@@ -544,7 +544,7 @@ void ide_proc_port_register_devices(ide_hwif_t *hwif)
                drive->proc = proc_mkdir(drive->name, parent);
                if (drive->proc) {
                        ide_add_proc_entries(drive->proc, generic_drive_entries, drive);
-                       proc_create_data("setting", S_IFREG|S_IRUSR|S_IWUSR,
+                       proc_create_data("settings", S_IFREG|S_IRUSR|S_IWUSR,
                                        drive->proc, &ide_settings_proc_fops,
                                        drive);
                }
index 031d568..4e339cf 100644 (file)
 #include <linux/iio/machine.h>
 #include <linux/iio/driver.h>
 
-#define AXP288_ADC_EN_MASK             0xF1
-#define AXP288_ADC_TS_PIN_GPADC                0xF2
-#define AXP288_ADC_TS_PIN_ON           0xF3
+/*
+ * This mask enables all ADCs except for the battery temp-sensor (TS), that is
+ * left as-is to avoid breaking charging on devices without a temp-sensor.
+ */
+#define AXP288_ADC_EN_MASK                             0xF0
+#define AXP288_ADC_TS_ENABLE                           0x01
+
+#define AXP288_ADC_TS_CURRENT_ON_OFF_MASK              GENMASK(1, 0)
+#define AXP288_ADC_TS_CURRENT_OFF                      (0 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_WHEN_CHARGING         (1 << 0)
+#define AXP288_ADC_TS_CURRENT_ON_ONDEMAND              (2 << 0)
+#define AXP288_ADC_TS_CURRENT_ON                       (3 << 0)
 
 enum axp288_adc_id {
        AXP288_ADC_TS,
@@ -44,6 +53,7 @@ enum axp288_adc_id {
 struct axp288_adc_info {
        int irq;
        struct regmap *regmap;
+       bool ts_enabled;
 };
 
 static const struct iio_chan_spec axp288_adc_channels[] = {
@@ -115,21 +125,33 @@ static int axp288_adc_read_channel(int *val, unsigned long address,
        return IIO_VAL_INT;
 }
 
-static int axp288_adc_set_ts(struct regmap *regmap, unsigned int mode,
-                               unsigned long address)
+/*
+ * The current-source used for the battery temp-sensor (TS) is shared
+ * with the GPADC. For proper fuel-gauge and charger operation the TS
+ * current-source needs to be permanently on. But to read the GPADC we
+ * need to temporary switch the TS current-source to ondemand, so that
+ * the GPADC can use it, otherwise we will always read an all 0 value.
+ */
+static int axp288_adc_set_ts(struct axp288_adc_info *info,
+                            unsigned int mode, unsigned long address)
 {
        int ret;
 
-       /* channels other than GPADC do not need to switch TS pin */
+       /* No need to switch the current-source if the TS pin is disabled */
+       if (!info->ts_enabled)
+               return 0;
+
+       /* Channels other than GPADC do not need the current source */
        if (address != AXP288_GP_ADC_H)
                return 0;
 
-       ret = regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, mode);
+       ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
+                                AXP288_ADC_TS_CURRENT_ON_OFF_MASK, mode);
        if (ret)
                return ret;
 
        /* When switching to the GPADC pin give things some time to settle */
-       if (mode == AXP288_ADC_TS_PIN_GPADC)
+       if (mode == AXP288_ADC_TS_CURRENT_ON_ONDEMAND)
                usleep_range(6000, 10000);
 
        return 0;
@@ -145,14 +167,14 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev,
        mutex_lock(&indio_dev->mlock);
        switch (mask) {
        case IIO_CHAN_INFO_RAW:
-               if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_GPADC,
+               if (axp288_adc_set_ts(info, AXP288_ADC_TS_CURRENT_ON_ONDEMAND,
                                        chan->address)) {
                        dev_err(&indio_dev->dev, "GPADC mode\n");
                        ret = -EINVAL;
                        break;
                }
                ret = axp288_adc_read_channel(val, chan->address, info->regmap);
-               if (axp288_adc_set_ts(info->regmap, AXP288_ADC_TS_PIN_ON,
+               if (axp288_adc_set_ts(info, AXP288_ADC_TS_CURRENT_ON,
                                                chan->address))
                        dev_err(&indio_dev->dev, "TS pin restore\n");
                break;
@@ -164,13 +186,35 @@ static int axp288_adc_read_raw(struct iio_dev *indio_dev,
        return ret;
 }
 
-static int axp288_adc_set_state(struct regmap *regmap)
+static int axp288_adc_initialize(struct axp288_adc_info *info)
 {
-       /* ADC should be always enabled for internal FG to function */
-       if (regmap_write(regmap, AXP288_ADC_TS_PIN_CTRL, AXP288_ADC_TS_PIN_ON))
-               return -EIO;
+       int ret, adc_enable_val;
+
+       /*
+        * Determine if the TS pin is enabled and set the TS current-source
+        * accordingly.
+        */
+       ret = regmap_read(info->regmap, AXP20X_ADC_EN1, &adc_enable_val);
+       if (ret)
+               return ret;
+
+       if (adc_enable_val & AXP288_ADC_TS_ENABLE) {
+               info->ts_enabled = true;
+               ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
+                                        AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+                                        AXP288_ADC_TS_CURRENT_ON);
+       } else {
+               info->ts_enabled = false;
+               ret = regmap_update_bits(info->regmap, AXP288_ADC_TS_PIN_CTRL,
+                                        AXP288_ADC_TS_CURRENT_ON_OFF_MASK,
+                                        AXP288_ADC_TS_CURRENT_OFF);
+       }
+       if (ret)
+               return ret;
 
-       return regmap_write(regmap, AXP20X_ADC_EN1, AXP288_ADC_EN_MASK);
+       /* Turn on the ADC for all channels except TS, leave TS as is */
+       return regmap_update_bits(info->regmap, AXP20X_ADC_EN1,
+                                 AXP288_ADC_EN_MASK, AXP288_ADC_EN_MASK);
 }
 
 static const struct iio_info axp288_adc_iio_info = {
@@ -200,7 +244,7 @@ static int axp288_adc_probe(struct platform_device *pdev)
         * Set ADC to enabled state at all time, including system suspend.
         * otherwise internal fuel gauge functionality may be affected.
         */
-       ret = axp288_adc_set_state(axp20x->regmap);
+       ret = axp288_adc_initialize(info);
        if (ret) {
                dev_err(&pdev->dev, "unable to enable ADC device\n");
                return ret;
index 184d686..8b4568e 100644 (file)
@@ -41,6 +41,7 @@
 
 #define ADS8688_VREF_MV                        4096
 #define ADS8688_REALBITS               16
+#define ADS8688_MAX_CHANNELS           8
 
 /*
  * enum ads8688_range - ADS8688 reference voltage range
@@ -385,7 +386,7 @@ static irqreturn_t ads8688_trigger_handler(int irq, void *p)
 {
        struct iio_poll_func *pf = p;
        struct iio_dev *indio_dev = pf->indio_dev;
-       u16 buffer[8];
+       u16 buffer[ADS8688_MAX_CHANNELS + sizeof(s64)/sizeof(u16)];
        int i, j = 0;
 
        for (i = 0; i < indio_dev->masklength; i++) {
index cafb1dc..9d984f2 100644 (file)
@@ -142,7 +142,10 @@ static void tiadc_step_config(struct iio_dev *indio_dev)
                        stepconfig |= STEPCONFIG_MODE_SWCNT;
 
                tiadc_writel(adc_dev, REG_STEPCONFIG(steps),
-                               stepconfig | STEPCONFIG_INP(chan));
+                               stepconfig | STEPCONFIG_INP(chan) |
+                               STEPCONFIG_INM_ADCREFM |
+                               STEPCONFIG_RFP_VREFP |
+                               STEPCONFIG_RFM_VREFN);
 
                if (adc_dev->open_delay[i] > STEPDELAY_OPEN_MASK) {
                        dev_warn(dev, "chan %d open delay truncating to 0x3FFFF\n",
index a406ad3..3a20cb5 100644 (file)
@@ -444,9 +444,8 @@ static int atlas_read_raw(struct iio_dev *indio_dev,
        case IIO_CHAN_INFO_SCALE:
                switch (chan->type) {
                case IIO_TEMP:
-                       *val = 1; /* 0.01 */
-                       *val2 = 100;
-                       break;
+                       *val = 10;
+                       return IIO_VAL_INT;
                case IIO_PH:
                        *val = 1; /* 0.001 */
                        *val2 = 1000;
@@ -477,7 +476,7 @@ static int atlas_write_raw(struct iio_dev *indio_dev,
                           int val, int val2, long mask)
 {
        struct atlas_data *data = iio_priv(indio_dev);
-       __be32 reg = cpu_to_be32(val);
+       __be32 reg = cpu_to_be32(val / 10);
 
        if (val2 != 0 || val < 0 || val > 20000)
                return -EINVAL;
index 63a7cc0..84f077b 100644 (file)
@@ -494,7 +494,10 @@ static void _cma_attach_to_dev(struct rdma_id_private *id_priv,
        id_priv->id.route.addr.dev_addr.transport =
                rdma_node_get_transport(cma_dev->device->node_type);
        list_add_tail(&id_priv->list, &cma_dev->id_list);
-       rdma_restrack_kadd(&id_priv->res);
+       if (id_priv->res.kern_name)
+               rdma_restrack_kadd(&id_priv->res);
+       else
+               rdma_restrack_uadd(&id_priv->res);
 }
 
 static void cma_attach_to_dev(struct rdma_id_private *id_priv,
index 3cd830d..6167343 100644 (file)
@@ -267,7 +267,6 @@ static inline int ib_mad_enforce_security(struct ib_mad_agent_private *map,
 #endif
 
 struct ib_device *ib_device_get_by_index(u32 ifindex);
-void ib_device_put(struct ib_device *device);
 /* RDMA device netlink */
 void nldev_init(void);
 void nldev_exit(void);
index 8872453..238ec42 100644 (file)
@@ -156,19 +156,26 @@ struct ib_device *ib_device_get_by_index(u32 index)
        down_read(&lists_rwsem);
        device = __ib_device_get_by_index(index);
        if (device) {
-               /* Do not return a device if unregistration has started. */
-               if (!refcount_inc_not_zero(&device->refcount))
+               if (!ib_device_try_get(device))
                        device = NULL;
        }
        up_read(&lists_rwsem);
        return device;
 }
 
+/**
+ * ib_device_put - Release IB device reference
+ * @device: device whose reference to be released
+ *
+ * ib_device_put() releases reference to the IB device to allow it to be
+ * unregistered and eventually free.
+ */
 void ib_device_put(struct ib_device *device)
 {
        if (refcount_dec_and_test(&device->refcount))
                complete(&device->unreg_completion);
 }
+EXPORT_SYMBOL(ib_device_put);
 
 static struct ib_device *__ib_device_get_by_name(const char *name)
 {
@@ -303,7 +310,6 @@ struct ib_device *ib_alloc_device(size_t size)
        rwlock_init(&device->client_data_lock);
        INIT_LIST_HEAD(&device->client_data_list);
        INIT_LIST_HEAD(&device->port_list);
-       refcount_set(&device->refcount, 1);
        init_completion(&device->unreg_completion);
 
        return device;
@@ -620,6 +626,7 @@ int ib_register_device(struct ib_device *device, const char *name,
                goto cg_cleanup;
        }
 
+       refcount_set(&device->refcount, 1);
        device->reg_state = IB_DEV_REGISTERED;
 
        list_for_each_entry(client, &client_list, list)
index e600fc2..3c97a8b 100644 (file)
@@ -584,10 +584,6 @@ static int fill_res_pd_entry(struct sk_buff *msg, struct netlink_callback *cb,
        if (nla_put_u64_64bit(msg, RDMA_NLDEV_ATTR_RES_USECNT,
                              atomic_read(&pd->usecnt), RDMA_NLDEV_ATTR_PAD))
                goto err;
-       if ((pd->flags & IB_PD_UNSAFE_GLOBAL_RKEY) &&
-           nla_put_u32(msg, RDMA_NLDEV_ATTR_RES_UNSAFE_GLOBAL_RKEY,
-                       pd->unsafe_global_rkey))
-               goto err;
 
        if (fill_res_name_pid(msg, res))
                goto err;
index be6b8e1..69f8db6 100644 (file)
@@ -106,6 +106,8 @@ int uverbs_finalize_object(struct ib_uobject *uobj,
                           enum uverbs_obj_access access,
                           bool commit);
 
+int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx);
+
 void setup_ufile_idr_uobject(struct ib_uverbs_file *ufile);
 void release_ufile_idr_uobject(struct ib_uverbs_file *ufile);
 
index a4ec430..acb882f 100644 (file)
@@ -352,6 +352,8 @@ struct ib_umem_odp *ib_alloc_odp_umem(struct ib_ucontext_per_mm *per_mm,
        umem->writable   = 1;
        umem->is_odp = 1;
        odp_data->per_mm = per_mm;
+       umem->owning_mm  = per_mm->mm;
+       mmgrab(umem->owning_mm);
 
        mutex_init(&odp_data->umem_mutex);
        init_completion(&odp_data->notifier_completion);
@@ -384,6 +386,7 @@ struct ib_umem_odp *ib_alloc_odp_umem(struct ib_ucontext_per_mm *per_mm,
 out_page_list:
        vfree(odp_data->page_list);
 out_odp_data:
+       mmdrop(umem->owning_mm);
        kfree(odp_data);
        return ERR_PTR(ret);
 }
index 6b12cc5..3317300 100644 (file)
@@ -60,6 +60,10 @@ static int uverbs_response(struct uverbs_attr_bundle *attrs, const void *resp,
 {
        int ret;
 
+       if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CORE_OUT))
+               return uverbs_copy_to_struct_or_zero(
+                       attrs, UVERBS_ATTR_CORE_OUT, resp, resp_len);
+
        if (copy_to_user(attrs->ucore.outbuf, resp,
                         min(attrs->ucore.outlen, resp_len)))
                return -EFAULT;
@@ -1181,6 +1185,9 @@ static int ib_uverbs_poll_cq(struct uverbs_attr_bundle *attrs)
                goto out_put;
        }
 
+       if (uverbs_attr_is_valid(attrs, UVERBS_ATTR_CORE_OUT))
+               ret = uverbs_output_written(attrs, UVERBS_ATTR_CORE_OUT);
+
        ret = 0;
 
 out_put:
@@ -2012,8 +2019,10 @@ static int ib_uverbs_post_send(struct uverbs_attr_bundle *attrs)
                return -ENOMEM;
 
        qp = uobj_get_obj_read(qp, UVERBS_OBJECT_QP, cmd.qp_handle, attrs);
-       if (!qp)
+       if (!qp) {
+               ret = -EINVAL;
                goto out;
+       }
 
        is_ud = qp->qp_type == IB_QPT_UD;
        sg_ind = 0;
index 8c81ff6..0ca04d2 100644 (file)
@@ -144,6 +144,21 @@ static bool uverbs_is_attr_cleared(const struct ib_uverbs_attr *uattr,
                           0, uattr->len - len);
 }
 
+static int uverbs_set_output(const struct uverbs_attr_bundle *bundle,
+                            const struct uverbs_attr *attr)
+{
+       struct bundle_priv *pbundle =
+               container_of(bundle, struct bundle_priv, bundle);
+       u16 flags;
+
+       flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags |
+               UVERBS_ATTR_F_VALID_OUTPUT;
+       if (put_user(flags,
+                    &pbundle->user_attrs[attr->ptr_attr.uattr_idx].flags))
+               return -EFAULT;
+       return 0;
+}
+
 static int uverbs_process_idrs_array(struct bundle_priv *pbundle,
                                     const struct uverbs_api_attr *attr_uapi,
                                     struct uverbs_objs_arr_attr *attr,
@@ -455,6 +470,19 @@ static int ib_uverbs_run_method(struct bundle_priv *pbundle,
                ret = handler(&pbundle->bundle);
        }
 
+       /*
+        * Until the drivers are revised to use the bundle directly we have to
+        * assume that the driver wrote to its UHW_OUT and flag userspace
+        * appropriately.
+        */
+       if (!ret && pbundle->method_elm->has_udata) {
+               const struct uverbs_attr *attr =
+                       uverbs_attr_get(&pbundle->bundle, UVERBS_ATTR_UHW_OUT);
+
+               if (!IS_ERR(attr))
+                       ret = uverbs_set_output(&pbundle->bundle, attr);
+       }
+
        /*
         * EPROTONOSUPPORT is ONLY to be returned if the ioctl framework can
         * not invoke the method because the request is not supported.  No
@@ -706,10 +734,7 @@ void uverbs_fill_udata(struct uverbs_attr_bundle *bundle,
 int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx,
                   const void *from, size_t size)
 {
-       struct bundle_priv *pbundle =
-               container_of(bundle, struct bundle_priv, bundle);
        const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
-       u16 flags;
        size_t min_size;
 
        if (IS_ERR(attr))
@@ -719,16 +744,25 @@ int uverbs_copy_to(const struct uverbs_attr_bundle *bundle, size_t idx,
        if (copy_to_user(u64_to_user_ptr(attr->ptr_attr.data), from, min_size))
                return -EFAULT;
 
-       flags = pbundle->uattrs[attr->ptr_attr.uattr_idx].flags |
-               UVERBS_ATTR_F_VALID_OUTPUT;
-       if (put_user(flags,
-                    &pbundle->user_attrs[attr->ptr_attr.uattr_idx].flags))
-               return -EFAULT;
-
-       return 0;
+       return uverbs_set_output(bundle, attr);
 }
 EXPORT_SYMBOL(uverbs_copy_to);
 
+
+/*
+ * This is only used if the caller has directly used copy_to_use to write the
+ * data.  It signals to user space that the buffer is filled in.
+ */
+int uverbs_output_written(const struct uverbs_attr_bundle *bundle, size_t idx)
+{
+       const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
+
+       if (IS_ERR(attr))
+               return PTR_ERR(attr);
+
+       return uverbs_set_output(bundle, attr);
+}
+
 int _uverbs_get_const(s64 *to, const struct uverbs_attr_bundle *attrs_bundle,
                      size_t idx, s64 lower_bound, u64 upper_bound,
                      s64  *def_val)
@@ -757,8 +791,10 @@ int uverbs_copy_to_struct_or_zero(const struct uverbs_attr_bundle *bundle,
 {
        const struct uverbs_attr *attr = uverbs_attr_get(bundle, idx);
 
-       if (clear_user(u64_to_user_ptr(attr->ptr_attr.data),
-                      attr->ptr_attr.len))
-               return -EFAULT;
+       if (size < attr->ptr_attr.len) {
+               if (clear_user(u64_to_user_ptr(attr->ptr_attr.data) + size,
+                              attr->ptr_attr.len - size))
+                       return -EFAULT;
+       }
        return uverbs_copy_to(bundle, idx, from, size);
 }
index fb0007a..5f36683 100644 (file)
@@ -204,6 +204,9 @@ void ib_uverbs_release_file(struct kref *ref)
        if (atomic_dec_and_test(&file->device->refcount))
                ib_uverbs_comp_dev(file->device);
 
+       if (file->async_file)
+               kref_put(&file->async_file->ref,
+                        ib_uverbs_release_async_event_file);
        put_device(&file->device->dev);
        kfree(file);
 }
@@ -690,6 +693,7 @@ static ssize_t ib_uverbs_write(struct file *filp, const char __user *buf,
 
        buf += sizeof(hdr);
 
+       memset(bundle.attr_present, 0, sizeof(bundle.attr_present));
        bundle.ufile = file;
        if (!method_elm->is_ex) {
                size_t in_len = hdr.in_words * 4 - sizeof(hdr);
@@ -963,11 +967,19 @@ void uverbs_user_mmap_disassociate(struct ib_uverbs_file *ufile)
 
                /* Get an arbitrary mm pointer that hasn't been cleaned yet */
                mutex_lock(&ufile->umap_lock);
-               if (!list_empty(&ufile->umaps)) {
-                       mm = list_first_entry(&ufile->umaps,
-                                             struct rdma_umap_priv, list)
-                                    ->vma->vm_mm;
-                       mmget(mm);
+               while (!list_empty(&ufile->umaps)) {
+                       int ret;
+
+                       priv = list_first_entry(&ufile->umaps,
+                                               struct rdma_umap_priv, list);
+                       mm = priv->vma->vm_mm;
+                       ret = mmget_not_zero(mm);
+                       if (!ret) {
+                               list_del_init(&priv->list);
+                               mm = NULL;
+                               continue;
+                       }
+                       break;
                }
                mutex_unlock(&ufile->umap_lock);
                if (!mm)
@@ -1095,10 +1107,6 @@ static int ib_uverbs_close(struct inode *inode, struct file *filp)
        list_del_init(&file->list);
        mutex_unlock(&file->device->lists_mutex);
 
-       if (file->async_file)
-               kref_put(&file->async_file->ref,
-                        ib_uverbs_release_async_event_file);
-
        kref_put(&file->ref, ib_uverbs_release_file);
 
        return 0;
index 5030ec4..2a3f2f0 100644 (file)
@@ -168,12 +168,18 @@ void copy_port_attr_to_resp(struct ib_port_attr *attr,
 static int UVERBS_HANDLER(UVERBS_METHOD_QUERY_PORT)(
        struct uverbs_attr_bundle *attrs)
 {
-       struct ib_device *ib_dev = attrs->ufile->device->ib_dev;
+       struct ib_device *ib_dev;
        struct ib_port_attr attr = {};
        struct ib_uverbs_query_port_resp_ex resp = {};
+       struct ib_ucontext *ucontext;
        int ret;
        u8 port_num;
 
+       ucontext = ib_uverbs_get_ucontext(attrs);
+       if (IS_ERR(ucontext))
+               return PTR_ERR(ucontext);
+       ib_dev = ucontext->device;
+
        /* FIXME: Extend the UAPI_DEF_OBJ_NEEDS_FN stuff.. */
        if (!ib_dev->ops.query_port)
                return -EOPNOTSUPP;
index 3268054..19551aa 100644 (file)
@@ -766,8 +766,8 @@ struct bnxt_qplib_rcfw_sbuf *bnxt_qplib_rcfw_alloc_sbuf(
                return NULL;
 
        sbuf->size = size;
-       sbuf->sb = dma_zalloc_coherent(&rcfw->pdev->dev, sbuf->size,
-                                      &sbuf->dma_addr, GFP_ATOMIC);
+       sbuf->sb = dma_alloc_coherent(&rcfw->pdev->dev, sbuf->size,
+                                     &sbuf->dma_addr, GFP_ATOMIC);
        if (!sbuf->sb)
                goto bail;
 
index 59eeac5..57d4951 100644 (file)
@@ -105,10 +105,10 @@ static int __alloc_pbl(struct pci_dev *pdev, struct bnxt_qplib_pbl *pbl,
 
        if (!sghead) {
                for (i = 0; i < pages; i++) {
-                       pbl->pg_arr[i] = dma_zalloc_coherent(&pdev->dev,
-                                                            pbl->pg_size,
-                                                            &pbl->pg_map_arr[i],
-                                                            GFP_KERNEL);
+                       pbl->pg_arr[i] = dma_alloc_coherent(&pdev->dev,
+                                                           pbl->pg_size,
+                                                           &pbl->pg_map_arr[i],
+                                                           GFP_KERNEL);
                        if (!pbl->pg_arr[i])
                                goto fail;
                        pbl->pg_count++;
index df4f7a3..8ac72ac 100644 (file)
@@ -291,9 +291,9 @@ int cxio_create_qp(struct cxio_rdev *rdev_p, u32 kernel_domain,
        if (!wq->sq)
                goto err3;
 
-       wq->queue = dma_zalloc_coherent(&(rdev_p->rnic_info.pdev->dev),
-                                            depth * sizeof(union t3_wr),
-                                            &(wq->dma_addr), GFP_KERNEL);
+       wq->queue = dma_alloc_coherent(&(rdev_p->rnic_info.pdev->dev),
+                                      depth * sizeof(union t3_wr),
+                                      &(wq->dma_addr), GFP_KERNEL);
        if (!wq->queue)
                goto err4;
 
index c13c0ba..d499cd6 100644 (file)
@@ -783,6 +783,7 @@ void c4iw_init_dev_ucontext(struct c4iw_rdev *rdev,
 static int c4iw_rdev_open(struct c4iw_rdev *rdev)
 {
        int err;
+       unsigned int factor;
 
        c4iw_init_dev_ucontext(rdev, &rdev->uctx);
 
@@ -806,8 +807,18 @@ static int c4iw_rdev_open(struct c4iw_rdev *rdev)
                return -EINVAL;
        }
 
-       rdev->qpmask = rdev->lldi.udb_density - 1;
-       rdev->cqmask = rdev->lldi.ucq_density - 1;
+       /* This implementation requires a sge_host_page_size <= PAGE_SIZE. */
+       if (rdev->lldi.sge_host_page_size > PAGE_SIZE) {
+               pr_err("%s: unsupported sge host page size %u\n",
+                      pci_name(rdev->lldi.pdev),
+                      rdev->lldi.sge_host_page_size);
+               return -EINVAL;
+       }
+
+       factor = PAGE_SIZE / rdev->lldi.sge_host_page_size;
+       rdev->qpmask = (rdev->lldi.udb_density * factor) - 1;
+       rdev->cqmask = (rdev->lldi.ucq_density * factor) - 1;
+
        pr_debug("dev %s stag start 0x%0x size 0x%0x num stags %d pbl start 0x%0x size 0x%0x rq start 0x%0x size 0x%0x qp qid start %u size %u cq qid start %u size %u srq size %u\n",
                 pci_name(rdev->lldi.pdev), rdev->lldi.vr->stag.start,
                 rdev->lldi.vr->stag.size, c4iw_num_stags(rdev),
index 981ff5c..504cf52 100644 (file)
@@ -2564,9 +2564,8 @@ static int alloc_srq_queue(struct c4iw_srq *srq, struct c4iw_dev_ucontext *uctx,
        wq->rqt_abs_idx = (wq->rqt_hwaddr - rdev->lldi.vr->rq.start) >>
                T4_RQT_ENTRY_SHIFT;
 
-       wq->queue = dma_zalloc_coherent(&rdev->lldi.pdev->dev,
-                                      wq->memsize, &wq->dma_addr,
-                       GFP_KERNEL);
+       wq->queue = dma_alloc_coherent(&rdev->lldi.pdev->dev, wq->memsize,
+                                      &wq->dma_addr, GFP_KERNEL);
        if (!wq->queue)
                goto err_free_rqtpool;
 
index c22ebc7..f9a7e9d 100644 (file)
@@ -488,7 +488,7 @@ static int hfi1_file_mmap(struct file *fp, struct vm_area_struct *vma)
                vmf = 1;
                break;
        case STATUS:
-               if (flags & (unsigned long)(VM_WRITE | VM_EXEC)) {
+               if (flags & VM_WRITE) {
                        ret = -EPERM;
                        goto done;
                }
index 0904490..7835eb5 100644 (file)
@@ -899,10 +899,10 @@ int hfi1_init(struct hfi1_devdata *dd, int reinit)
                goto done;
 
        /* allocate dummy tail memory for all receive contexts */
-       dd->rcvhdrtail_dummy_kvaddr = dma_zalloc_coherent(
-               &dd->pcidev->dev, sizeof(u64),
-               &dd->rcvhdrtail_dummy_dma,
-               GFP_KERNEL);
+       dd->rcvhdrtail_dummy_kvaddr = dma_alloc_coherent(&dd->pcidev->dev,
+                                                        sizeof(u64),
+                                                        &dd->rcvhdrtail_dummy_dma,
+                                                        GFP_KERNEL);
 
        if (!dd->rcvhdrtail_dummy_kvaddr) {
                dd_dev_err(dd, "cannot allocate dummy tail memory\n");
@@ -1863,9 +1863,9 @@ int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd)
                        gfp_flags = GFP_KERNEL;
                else
                        gfp_flags = GFP_USER;
-               rcd->rcvhdrq = dma_zalloc_coherent(
-                       &dd->pcidev->dev, amt, &rcd->rcvhdrq_dma,
-                       gfp_flags | __GFP_COMP);
+               rcd->rcvhdrq = dma_alloc_coherent(&dd->pcidev->dev, amt,
+                                                 &rcd->rcvhdrq_dma,
+                                                 gfp_flags | __GFP_COMP);
 
                if (!rcd->rcvhdrq) {
                        dd_dev_err(dd,
@@ -1876,9 +1876,10 @@ int hfi1_create_rcvhdrq(struct hfi1_devdata *dd, struct hfi1_ctxtdata *rcd)
 
                if (HFI1_CAP_KGET_MASK(rcd->flags, DMA_RTAIL) ||
                    HFI1_CAP_UGET_MASK(rcd->flags, DMA_RTAIL)) {
-                       rcd->rcvhdrtail_kvaddr = dma_zalloc_coherent(
-                               &dd->pcidev->dev, PAGE_SIZE,
-                               &rcd->rcvhdrqtailaddr_dma, gfp_flags);
+                       rcd->rcvhdrtail_kvaddr = dma_alloc_coherent(&dd->pcidev->dev,
+                                                                   PAGE_SIZE,
+                                                                   &rcd->rcvhdrqtailaddr_dma,
+                                                                   gfp_flags);
                        if (!rcd->rcvhdrtail_kvaddr)
                                goto bail_free;
                }
@@ -1974,10 +1975,10 @@ int hfi1_setup_eagerbufs(struct hfi1_ctxtdata *rcd)
        while (alloced_bytes < rcd->egrbufs.size &&
               rcd->egrbufs.alloced < rcd->egrbufs.count) {
                rcd->egrbufs.buffers[idx].addr =
-                       dma_zalloc_coherent(&dd->pcidev->dev,
-                                           rcd->egrbufs.rcvtid_size,
-                                           &rcd->egrbufs.buffers[idx].dma,
-                                           gfp_flags);
+                       dma_alloc_coherent(&dd->pcidev->dev,
+                                          rcd->egrbufs.rcvtid_size,
+                                          &rcd->egrbufs.buffers[idx].dma,
+                                          gfp_flags);
                if (rcd->egrbufs.buffers[idx].addr) {
                        rcd->egrbufs.buffers[idx].len =
                                rcd->egrbufs.rcvtid_size;
index dd5a5c0..04126d7 100644 (file)
@@ -2098,11 +2098,10 @@ int init_credit_return(struct hfi1_devdata *dd)
                int bytes = TXE_NUM_CONTEXTS * sizeof(struct credit_return);
 
                set_dev_node(&dd->pcidev->dev, i);
-               dd->cr_base[i].va = dma_zalloc_coherent(
-                                       &dd->pcidev->dev,
-                                       bytes,
-                                       &dd->cr_base[i].dma,
-                                       GFP_KERNEL);
+               dd->cr_base[i].va = dma_alloc_coherent(&dd->pcidev->dev,
+                                                      bytes,
+                                                      &dd->cr_base[i].dma,
+                                                      GFP_KERNEL);
                if (!dd->cr_base[i].va) {
                        set_dev_node(&dd->pcidev->dev, dd->node);
                        dd_dev_err(dd,
index b84356e..96897a9 100644 (file)
@@ -1453,12 +1453,9 @@ int sdma_init(struct hfi1_devdata *dd, u8 port)
                timer_setup(&sde->err_progress_check_timer,
                            sdma_err_progress_check, 0);
 
-               sde->descq = dma_zalloc_coherent(
-                       &dd->pcidev->dev,
-                       descq_cnt * sizeof(u64[2]),
-                       &sde->descq_phys,
-                       GFP_KERNEL
-               );
+               sde->descq = dma_alloc_coherent(&dd->pcidev->dev,
+                                               descq_cnt * sizeof(u64[2]),
+                                               &sde->descq_phys, GFP_KERNEL);
                if (!sde->descq)
                        goto bail;
                sde->tx_ring =
@@ -1471,24 +1468,18 @@ int sdma_init(struct hfi1_devdata *dd, u8 port)
 
        dd->sdma_heads_size = L1_CACHE_BYTES * num_engines;
        /* Allocate memory for DMA of head registers to memory */
-       dd->sdma_heads_dma = dma_zalloc_coherent(
-               &dd->pcidev->dev,
-               dd->sdma_heads_size,
-               &dd->sdma_heads_phys,
-               GFP_KERNEL
-       );
+       dd->sdma_heads_dma = dma_alloc_coherent(&dd->pcidev->dev,
+                                               dd->sdma_heads_size,
+                                               &dd->sdma_heads_phys,
+                                               GFP_KERNEL);
        if (!dd->sdma_heads_dma) {
                dd_dev_err(dd, "failed to allocate SendDMA head memory\n");
                goto bail;
        }
 
        /* Allocate memory for pad */
-       dd->sdma_pad_dma = dma_zalloc_coherent(
-               &dd->pcidev->dev,
-               sizeof(u32),
-               &dd->sdma_pad_phys,
-               GFP_KERNEL
-       );
+       dd->sdma_pad_dma = dma_alloc_coherent(&dd->pcidev->dev, sizeof(u32),
+                                             &dd->sdma_pad_phys, GFP_KERNEL);
        if (!dd->sdma_pad_dma) {
                dd_dev_err(dd, "failed to allocate SendDMA pad memory\n");
                goto bail;
index 88242fe..bf96067 100644 (file)
@@ -987,7 +987,6 @@ void hfi1_ud_rcv(struct hfi1_packet *packet)
            opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) {
                wc.ex.imm_data = packet->ohdr->u.ud.imm_data;
                wc.wc_flags = IB_WC_WITH_IMM;
-               tlen -= sizeof(u32);
        } else if (opcode == IB_OPCODE_UD_SEND_ONLY) {
                wc.ex.imm_data = 0;
                wc.wc_flags = 0;
index 6300033..dac058d 100644 (file)
@@ -197,8 +197,8 @@ int hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, u32 max_direct,
                buf->npages = 1 << order;
                buf->page_shift = page_shift;
                /* MTT PA must be recorded in 4k alignment, t is 4k aligned */
-               buf->direct.buf = dma_zalloc_coherent(dev,
-                                                     size, &t, GFP_KERNEL);
+               buf->direct.buf = dma_alloc_coherent(dev, size, &t,
+                                                    GFP_KERNEL);
                if (!buf->direct.buf)
                        return -ENOMEM;
 
@@ -219,9 +219,10 @@ int hns_roce_buf_alloc(struct hns_roce_dev *hr_dev, u32 size, u32 max_direct,
                        return -ENOMEM;
 
                for (i = 0; i < buf->nbufs; ++i) {
-                       buf->page_list[i].buf = dma_zalloc_coherent(dev,
-                                                                 page_size, &t,
-                                                                 GFP_KERNEL);
+                       buf->page_list[i].buf = dma_alloc_coherent(dev,
+                                                                  page_size,
+                                                                  &t,
+                                                                  GFP_KERNEL);
 
                        if (!buf->page_list[i].buf)
                                goto err_free;
index 3a66945..543fa15 100644 (file)
@@ -5091,7 +5091,7 @@ static int hns_roce_mhop_alloc_eq(struct hns_roce_dev *hr_dev,
                                eqe_alloc = i * (buf_chk_sz / eq->eqe_size);
                                size = (eq->entries - eqe_alloc) * eq->eqe_size;
                        }
-                       eq->buf[i] = dma_zalloc_coherent(dev, size,
+                       eq->buf[i] = dma_alloc_coherent(dev, size,
                                                        &(eq->buf_dma[i]),
                                                        GFP_KERNEL);
                        if (!eq->buf[i])
@@ -5126,9 +5126,9 @@ static int hns_roce_mhop_alloc_eq(struct hns_roce_dev *hr_dev,
                                        size = (eq->entries - eqe_alloc)
                                                * eq->eqe_size;
                                }
-                               eq->buf[idx] = dma_zalloc_coherent(dev, size,
-                                                           &(eq->buf_dma[idx]),
-                                                           GFP_KERNEL);
+                               eq->buf[idx] = dma_alloc_coherent(dev, size,
+                                                                 &(eq->buf_dma[idx]),
+                                                                 GFP_KERNEL);
                                if (!eq->buf[idx])
                                        goto err_dma_alloc_buf;
 
@@ -5241,7 +5241,7 @@ static int hns_roce_v2_create_eq(struct hns_roce_dev *hr_dev,
                        goto free_cmd_mbox;
                }
 
-               eq->buf_list->buf = dma_zalloc_coherent(dev, buf_chk_sz,
+               eq->buf_list->buf = dma_alloc_coherent(dev, buf_chk_sz,
                                                       &(eq->buf_list->map),
                                                       GFP_KERNEL);
                if (!eq->buf_list->buf) {
index 960b194..12deacf 100644 (file)
@@ -210,6 +210,7 @@ struct ib_srq *hns_roce_create_srq(struct ib_pd *pd,
                                   struct ib_udata *udata)
 {
        struct hns_roce_dev *hr_dev = to_hr_dev(pd->device);
+       struct hns_roce_ib_create_srq_resp resp = {};
        struct hns_roce_srq *srq;
        int srq_desc_size;
        int srq_buf_size;
@@ -378,16 +379,21 @@ struct ib_srq *hns_roce_create_srq(struct ib_pd *pd,
 
        srq->event = hns_roce_ib_srq_event;
        srq->ibsrq.ext.xrc.srq_num = srq->srqn;
+       resp.srqn = srq->srqn;
 
        if (udata) {
-               if (ib_copy_to_udata(udata, &srq->srqn, sizeof(__u32))) {
+               if (ib_copy_to_udata(udata, &resp,
+                                    min(udata->outlen, sizeof(resp)))) {
                        ret = -EFAULT;
-                       goto err_wrid;
+                       goto err_srqc_alloc;
                }
        }
 
        return &srq->ibsrq;
 
+err_srqc_alloc:
+       hns_roce_srq_free(hr_dev, srq);
+
 err_wrid:
        kvfree(srq->wrid);
 
index a9ea966..59e9781 100644 (file)
@@ -745,8 +745,8 @@ enum i40iw_status_code i40iw_allocate_dma_mem(struct i40iw_hw *hw,
        if (!mem)
                return I40IW_ERR_PARAM;
        mem->size = ALIGN(size, alignment);
-       mem->va = dma_zalloc_coherent(&pcidev->dev, mem->size,
-                                     (dma_addr_t *)&mem->pa, GFP_KERNEL);
+       mem->va = dma_alloc_coherent(&pcidev->dev, mem->size,
+                                    (dma_addr_t *)&mem->pa, GFP_KERNEL);
        if (!mem->va)
                return I40IW_ERR_NO_MEMORY;
        return 0;
index 25439da..936ee13 100644 (file)
@@ -1411,7 +1411,7 @@ int mlx4_ib_send_to_wire(struct mlx4_ib_dev *dev, int slave, u8 port,
 
        sqp_mad = (struct mlx4_mad_snd_buf *) (sqp->tx_ring[wire_tx_ix].buf.addr);
        if (sqp->tx_ring[wire_tx_ix].ah)
-               rdma_destroy_ah(sqp->tx_ring[wire_tx_ix].ah, 0);
+               mlx4_ib_destroy_ah(sqp->tx_ring[wire_tx_ix].ah, 0);
        sqp->tx_ring[wire_tx_ix].ah = ah;
        ib_dma_sync_single_for_cpu(&dev->ib_dev,
                                   sqp->tx_ring[wire_tx_ix].buf.map,
@@ -1902,7 +1902,7 @@ static void mlx4_ib_sqp_comp_worker(struct work_struct *work)
                if (wc.status == IB_WC_SUCCESS) {
                        switch (wc.opcode) {
                        case IB_WC_SEND:
-                               rdma_destroy_ah(sqp->tx_ring[wc.wr_id &
+                               mlx4_ib_destroy_ah(sqp->tx_ring[wc.wr_id &
                                              (MLX4_NUM_TUNNEL_BUFS - 1)].ah, 0);
                                sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
                                        = NULL;
@@ -1931,7 +1931,7 @@ static void mlx4_ib_sqp_comp_worker(struct work_struct *work)
                                 " status = %d, wrid = 0x%llx\n",
                                 ctx->slave, wc.status, wc.wr_id);
                        if (!MLX4_TUN_IS_RECV(wc.wr_id)) {
-                               rdma_destroy_ah(sqp->tx_ring[wc.wr_id &
+                               mlx4_ib_destroy_ah(sqp->tx_ring[wc.wr_id &
                                              (MLX4_NUM_TUNNEL_BUFS - 1)].ah, 0);
                                sqp->tx_ring[wc.wr_id & (MLX4_NUM_TUNNEL_BUFS - 1)].ah
                                        = NULL;
index e8a1e44..798591a 100644 (file)
@@ -630,8 +630,7 @@ const struct uapi_definition mlx5_ib_flow_defs[] = {
                UAPI_DEF_IS_OBJ_SUPPORTED(flow_is_supported)),
        UAPI_DEF_CHAIN_OBJ_TREE(
                UVERBS_OBJECT_FLOW,
-               &mlx5_ib_fs,
-               UAPI_DEF_IS_OBJ_SUPPORTED(flow_is_supported)),
+               &mlx5_ib_fs),
        UAPI_DEF_CHAIN_OBJ_TREE(UVERBS_OBJECT_FLOW_ACTION,
                                &mlx5_ib_flow_actions),
        {},
index 01e0f62..4ee3296 100644 (file)
@@ -1595,10 +1595,12 @@ static void mlx5_ib_prefetch_mr_work(struct work_struct *work)
        struct prefetch_mr_work *w =
                container_of(work, struct prefetch_mr_work, work);
 
-       if (w->dev->ib_dev.reg_state == IB_DEV_REGISTERED)
+       if (ib_device_try_get(&w->dev->ib_dev)) {
                mlx5_ib_prefetch_sg_list(w->dev, w->pf_flags, w->sg_list,
                                         w->num_sge);
-
+               ib_device_put(&w->dev->ib_dev);
+       }
+       put_device(&w->dev->ib_dev.dev);
        kfree(w);
 }
 
@@ -1617,15 +1619,13 @@ int mlx5_ib_advise_mr_prefetch(struct ib_pd *pd,
                return mlx5_ib_prefetch_sg_list(dev, pf_flags, sg_list,
                                                num_sge);
 
-       if (dev->ib_dev.reg_state != IB_DEV_REGISTERED)
-               return -ENODEV;
-
        work = kvzalloc(struct_size(work, sg_list, num_sge), GFP_KERNEL);
        if (!work)
                return -ENOMEM;
 
        memcpy(work->sg_list, sg_list, num_sge * sizeof(struct ib_sge));
 
+       get_device(&dev->ib_dev.dev);
        work->dev = dev;
        work->pf_flags = pf_flags;
        work->num_sge = num_sge;
index dd2ae64..7db778d 100644 (file)
@@ -1912,14 +1912,16 @@ static int create_qp_common(struct mlx5_ib_dev *dev, struct ib_pd *pd,
                }
 
                if (!check_flags_mask(ucmd.flags,
+                                     MLX5_QP_FLAG_ALLOW_SCATTER_CQE |
+                                     MLX5_QP_FLAG_BFREG_INDEX |
+                                     MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE |
+                                     MLX5_QP_FLAG_SCATTER_CQE |
                                      MLX5_QP_FLAG_SIGNATURE |
-                                             MLX5_QP_FLAG_SCATTER_CQE |
-                                             MLX5_QP_FLAG_TUNNEL_OFFLOADS |
-                                             MLX5_QP_FLAG_BFREG_INDEX |
-                                             MLX5_QP_FLAG_TYPE_DCT |
-                                             MLX5_QP_FLAG_TYPE_DCI |
-                                             MLX5_QP_FLAG_ALLOW_SCATTER_CQE |
-                                             MLX5_QP_FLAG_PACKET_BASED_CREDIT_MODE))
+                                     MLX5_QP_FLAG_TIR_ALLOW_SELF_LB_MC |
+                                     MLX5_QP_FLAG_TIR_ALLOW_SELF_LB_UC |
+                                     MLX5_QP_FLAG_TUNNEL_OFFLOADS |
+                                     MLX5_QP_FLAG_TYPE_DCI |
+                                     MLX5_QP_FLAG_TYPE_DCT))
                        return -EINVAL;
 
                err = get_qp_user_index(to_mucontext(pd->uobject->context),
index cc9c0c8..112d2f3 100644 (file)
@@ -623,8 +623,9 @@ int mthca_alloc_db(struct mthca_dev *dev, enum mthca_db_type type,
        page = dev->db_tab->page + end;
 
 alloc:
-       page->db_rec = dma_zalloc_coherent(&dev->pdev->dev, MTHCA_ICM_PAGE_SIZE,
-                                          &page->mapping, GFP_KERNEL);
+       page->db_rec = dma_alloc_coherent(&dev->pdev->dev,
+                                         MTHCA_ICM_PAGE_SIZE, &page->mapping,
+                                         GFP_KERNEL);
        if (!page->db_rec) {
                ret = -ENOMEM;
                goto out;
index 82cb6b7..e3e9dd5 100644 (file)
@@ -534,7 +534,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
        {
                struct mthca_ucontext *context;
 
-               qp = kmalloc(sizeof *qp, GFP_KERNEL);
+               qp = kzalloc(sizeof(*qp), GFP_KERNEL);
                if (!qp)
                        return ERR_PTR(-ENOMEM);
 
@@ -600,7 +600,7 @@ static struct ib_qp *mthca_create_qp(struct ib_pd *pd,
                if (udata)
                        return ERR_PTR(-EINVAL);
 
-               qp = kmalloc(sizeof (struct mthca_sqp), GFP_KERNEL);
+               qp = kzalloc(sizeof(struct mthca_sqp), GFP_KERNEL);
                if (!qp)
                        return ERR_PTR(-ENOMEM);
 
index 241a57a..097e5ab 100644 (file)
@@ -380,8 +380,8 @@ static int ocrdma_alloc_q(struct ocrdma_dev *dev,
        q->len = len;
        q->entry_size = entry_size;
        q->size = len * entry_size;
-       q->va = dma_zalloc_coherent(&dev->nic_info.pdev->dev, q->size,
-                                   &q->dma, GFP_KERNEL);
+       q->va = dma_alloc_coherent(&dev->nic_info.pdev->dev, q->size, &q->dma,
+                                  GFP_KERNEL);
        if (!q->va)
                return -ENOMEM;
        return 0;
@@ -1819,7 +1819,7 @@ int ocrdma_mbx_create_cq(struct ocrdma_dev *dev, struct ocrdma_cq *cq,
                return -ENOMEM;
        ocrdma_init_mch(&cmd->cmd.req, OCRDMA_CMD_CREATE_CQ,
                        OCRDMA_SUBSYS_COMMON, sizeof(*cmd));
-       cq->va = dma_zalloc_coherent(&pdev->dev, cq->len, &cq->pa, GFP_KERNEL);
+       cq->va = dma_alloc_coherent(&pdev->dev, cq->len, &cq->pa, GFP_KERNEL);
        if (!cq->va) {
                status = -ENOMEM;
                goto mem_err;
@@ -2209,7 +2209,7 @@ static int ocrdma_set_create_qp_sq_cmd(struct ocrdma_create_qp_req *cmd,
        qp->sq.max_cnt = max_wqe_allocated;
        len = (hw_pages * hw_page_size);
 
-       qp->sq.va = dma_zalloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
+       qp->sq.va = dma_alloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
        if (!qp->sq.va)
                return -EINVAL;
        qp->sq.len = len;
@@ -2259,7 +2259,7 @@ static int ocrdma_set_create_qp_rq_cmd(struct ocrdma_create_qp_req *cmd,
        qp->rq.max_cnt = max_rqe_allocated;
        len = (hw_pages * hw_page_size);
 
-       qp->rq.va = dma_zalloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
+       qp->rq.va = dma_alloc_coherent(&pdev->dev, len, &pa, GFP_KERNEL);
        if (!qp->rq.va)
                return -ENOMEM;
        qp->rq.pa = pa;
@@ -2315,8 +2315,8 @@ static int ocrdma_set_create_qp_ird_cmd(struct ocrdma_create_qp_req *cmd,
        if (dev->attr.ird == 0)
                return 0;
 
-       qp->ird_q_va = dma_zalloc_coherent(&pdev->dev, ird_q_len, &pa,
-                                          GFP_KERNEL);
+       qp->ird_q_va = dma_alloc_coherent(&pdev->dev, ird_q_len, &pa,
+                                         GFP_KERNEL);
        if (!qp->ird_q_va)
                return -ENOMEM;
        ocrdma_build_q_pages(&cmd->ird_addr[0], dev->attr.num_ird_pages,
index dd15474..6be0ea1 100644 (file)
@@ -73,8 +73,8 @@ bool ocrdma_alloc_stats_resources(struct ocrdma_dev *dev)
        mem->size = max_t(u32, sizeof(struct ocrdma_rdma_stats_req),
                        sizeof(struct ocrdma_rdma_stats_resp));
 
-       mem->va = dma_zalloc_coherent(&dev->nic_info.pdev->dev, mem->size,
-                                     &mem->pa, GFP_KERNEL);
+       mem->va = dma_alloc_coherent(&dev->nic_info.pdev->dev, mem->size,
+                                    &mem->pa, GFP_KERNEL);
        if (!mem->va) {
                pr_err("%s: stats mbox allocation failed\n", __func__);
                return false;
index c46bed0..287c332 100644 (file)
@@ -504,8 +504,8 @@ struct ib_ucontext *ocrdma_alloc_ucontext(struct ib_device *ibdev,
        INIT_LIST_HEAD(&ctx->mm_head);
        mutex_init(&ctx->mm_list_lock);
 
-       ctx->ah_tbl.va = dma_zalloc_coherent(&pdev->dev, map_len,
-                                            &ctx->ah_tbl.pa, GFP_KERNEL);
+       ctx->ah_tbl.va = dma_alloc_coherent(&pdev->dev, map_len,
+                                           &ctx->ah_tbl.pa, GFP_KERNEL);
        if (!ctx->ah_tbl.va) {
                kfree(ctx);
                return ERR_PTR(-ENOMEM);
@@ -838,7 +838,7 @@ static int ocrdma_build_pbl_tbl(struct ocrdma_dev *dev, struct ocrdma_hw_mr *mr)
                return -ENOMEM;
 
        for (i = 0; i < mr->num_pbls; i++) {
-               va = dma_zalloc_coherent(&pdev->dev, dma_len, &pa, GFP_KERNEL);
+               va = dma_alloc_coherent(&pdev->dev, dma_len, &pa, GFP_KERNEL);
                if (!va) {
                        ocrdma_free_mr_pbl_tbl(dev, mr);
                        status = -ENOMEM;
index b342a70..e1ccf32 100644 (file)
@@ -556,8 +556,8 @@ static struct qedr_pbl *qedr_alloc_pbl_tbl(struct qedr_dev *dev,
                return ERR_PTR(-ENOMEM);
 
        for (i = 0; i < pbl_info->num_pbls; i++) {
-               va = dma_zalloc_coherent(&pdev->dev, pbl_info->pbl_size,
-                                        &pa, flags);
+               va = dma_alloc_coherent(&pdev->dev, pbl_info->pbl_size, &pa,
+                                       flags);
                if (!va)
                        goto err;
 
index 868da0e..445ea19 100644 (file)
@@ -512,7 +512,6 @@ void qib_ud_rcv(struct qib_ibport *ibp, struct ib_header *hdr,
            opcode == IB_OPCODE_UD_SEND_ONLY_WITH_IMMEDIATE) {
                wc.ex.imm_data = ohdr->u.ud.imm_data;
                wc.wc_flags = IB_WC_WITH_IMM;
-               tlen -= sizeof(u32);
        } else if (opcode == IB_OPCODE_UD_SEND_ONLY) {
                wc.ex.imm_data = 0;
                wc.wc_flags = 0;
index 42b8685..3c633ab 100644 (file)
@@ -427,7 +427,40 @@ static inline enum ib_qp_state pvrdma_qp_state_to_ib(enum pvrdma_qp_state state)
 
 static inline enum pvrdma_wr_opcode ib_wr_opcode_to_pvrdma(enum ib_wr_opcode op)
 {
-       return (enum pvrdma_wr_opcode)op;
+       switch (op) {
+       case IB_WR_RDMA_WRITE:
+               return PVRDMA_WR_RDMA_WRITE;
+       case IB_WR_RDMA_WRITE_WITH_IMM:
+               return PVRDMA_WR_RDMA_WRITE_WITH_IMM;
+       case IB_WR_SEND:
+               return PVRDMA_WR_SEND;
+       case IB_WR_SEND_WITH_IMM:
+               return PVRDMA_WR_SEND_WITH_IMM;
+       case IB_WR_RDMA_READ:
+               return PVRDMA_WR_RDMA_READ;
+       case IB_WR_ATOMIC_CMP_AND_SWP:
+               return PVRDMA_WR_ATOMIC_CMP_AND_SWP;
+       case IB_WR_ATOMIC_FETCH_AND_ADD:
+               return PVRDMA_WR_ATOMIC_FETCH_AND_ADD;
+       case IB_WR_LSO:
+               return PVRDMA_WR_LSO;
+       case IB_WR_SEND_WITH_INV:
+               return PVRDMA_WR_SEND_WITH_INV;
+       case IB_WR_RDMA_READ_WITH_INV:
+               return PVRDMA_WR_RDMA_READ_WITH_INV;
+       case IB_WR_LOCAL_INV:
+               return PVRDMA_WR_LOCAL_INV;
+       case IB_WR_REG_MR:
+               return PVRDMA_WR_FAST_REG_MR;
+       case IB_WR_MASKED_ATOMIC_CMP_AND_SWP:
+               return PVRDMA_WR_MASKED_ATOMIC_CMP_AND_SWP;
+       case IB_WR_MASKED_ATOMIC_FETCH_AND_ADD:
+               return PVRDMA_WR_MASKED_ATOMIC_FETCH_AND_ADD;
+       case IB_WR_REG_SIG_MR:
+               return PVRDMA_WR_REG_SIG_MR;
+       default:
+               return PVRDMA_WR_ERROR;
+       }
 }
 
 static inline enum ib_wc_status pvrdma_wc_status_to_ib(
index eaa109d..39c37b6 100644 (file)
@@ -890,8 +890,8 @@ static int pvrdma_pci_probe(struct pci_dev *pdev,
        dev_info(&pdev->dev, "device version %d, driver version %d\n",
                 dev->dsr_version, PVRDMA_VERSION);
 
-       dev->dsr = dma_zalloc_coherent(&pdev->dev, sizeof(*dev->dsr),
-                                      &dev->dsrbase, GFP_KERNEL);
+       dev->dsr = dma_alloc_coherent(&pdev->dev, sizeof(*dev->dsr),
+                                     &dev->dsrbase, GFP_KERNEL);
        if (!dev->dsr) {
                dev_err(&pdev->dev, "failed to allocate shared region\n");
                ret = -ENOMEM;
index 3acf74c..1ec3646 100644 (file)
@@ -721,6 +721,12 @@ int pvrdma_post_send(struct ib_qp *ibqp, const struct ib_send_wr *wr,
                    wr->opcode == IB_WR_RDMA_WRITE_WITH_IMM)
                        wqe_hdr->ex.imm_data = wr->ex.imm_data;
 
+               if (unlikely(wqe_hdr->opcode == PVRDMA_WR_ERROR)) {
+                       *bad_wr = wr;
+                       ret = -EINVAL;
+                       goto out;
+               }
+
                switch (qp->ibqp.qp_type) {
                case IB_QPT_GSI:
                case IB_QPT_UD:
index a1bd8cf..c6cc3e4 100644 (file)
@@ -2910,6 +2910,8 @@ send:
                        goto op_err;
                if (!ret)
                        goto rnr_nak;
+               if (wqe->length > qp->r_len)
+                       goto inv_err;
                break;
 
        case IB_WR_RDMA_WRITE_WITH_IMM:
@@ -3078,7 +3080,10 @@ op_err:
        goto err;
 
 inv_err:
-       send_status = IB_WC_REM_INV_REQ_ERR;
+       send_status =
+               sqp->ibqp.qp_type == IB_QPT_RC ?
+                       IB_WC_REM_INV_REQ_ERR :
+                       IB_WC_SUCCESS;
        wc.status = IB_WC_LOC_QP_OP_ERR;
        goto err;
 
index 1da119d..73e808c 100644 (file)
@@ -248,7 +248,6 @@ struct ipoib_cm_tx {
        struct list_head     list;
        struct net_device   *dev;
        struct ipoib_neigh  *neigh;
-       struct ipoib_path   *path;
        struct ipoib_tx_buf *tx_ring;
        unsigned int         tx_head;
        unsigned int         tx_tail;
index 0428e01..aa9dcfc 100644 (file)
@@ -1312,7 +1312,6 @@ struct ipoib_cm_tx *ipoib_cm_create_tx(struct net_device *dev, struct ipoib_path
 
        neigh->cm = tx;
        tx->neigh = neigh;
-       tx->path = path;
        tx->dev = dev;
        list_add(&tx->list, &priv->cm.start_list);
        set_bit(IPOIB_FLAG_INITIALIZED, &tx->flags);
@@ -1371,7 +1370,7 @@ static void ipoib_cm_tx_start(struct work_struct *work)
                                neigh->daddr + QPN_AND_OPTIONS_OFFSET);
                        goto free_neigh;
                }
-               memcpy(&pathrec, &p->path->pathrec, sizeof(pathrec));
+               memcpy(&pathrec, &path->pathrec, sizeof(pathrec));
 
                spin_unlock_irqrestore(&priv->lock, flags);
                netif_tx_unlock_bh(dev);
index 31d9153..694324b 100644 (file)
@@ -3032,7 +3032,6 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
 {
        struct srp_target_port *target = host_to_target(scmnd->device->host);
        struct srp_rdma_ch *ch;
-       int i, j;
        u8 status;
 
        shost_printk(KERN_ERR, target->scsi_host, "SRP reset_device called\n");
@@ -3044,15 +3043,6 @@ static int srp_reset_device(struct scsi_cmnd *scmnd)
        if (status)
                return FAILED;
 
-       for (i = 0; i < target->ch_count; i++) {
-               ch = &target->ch[i];
-               for (j = 0; j < target->req_ring_size; ++j) {
-                       struct srp_request *req = &ch->req_ring[j];
-
-                       srp_finish_req(ch, req, scmnd->device, DID_RESET << 16);
-               }
-       }
-
        return SUCCESS;
 }
 
index cfc8b94..aa4e431 100644 (file)
@@ -252,6 +252,8 @@ static const struct xpad_device {
        { 0x0f30, 0x0202, "Joytech Advanced Controller", 0, XTYPE_XBOX },
        { 0x0f30, 0x8888, "BigBen XBMiniPad Controller", 0, XTYPE_XBOX },
        { 0x102c, 0xff0c, "Joytech Wireless Advanced Controller", 0, XTYPE_XBOX },
+       { 0x1038, 0x1430, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
+       { 0x1038, 0x1431, "SteelSeries Stratus Duo", 0, XTYPE_XBOX360 },
        { 0x11c9, 0x55f0, "Nacon GC-100XF", 0, XTYPE_XBOX360 },
        { 0x12ab, 0x0004, "Honey Bee Xbox360 dancepad", MAP_DPAD_TO_BUTTONS, XTYPE_XBOX360 },
        { 0x12ab, 0x0301, "PDP AFTERGLOW AX.1", 0, XTYPE_XBOX360 },
@@ -428,6 +430,7 @@ static const struct usb_device_id xpad_table[] = {
        XPAD_XBOXONE_VENDOR(0x0e6f),            /* 0x0e6f X-Box One controllers */
        XPAD_XBOX360_VENDOR(0x0f0d),            /* Hori Controllers */
        XPAD_XBOXONE_VENDOR(0x0f0d),            /* Hori Controllers */
+       XPAD_XBOX360_VENDOR(0x1038),            /* SteelSeries Controllers */
        XPAD_XBOX360_VENDOR(0x11c9),            /* Nacon GC100XF */
        XPAD_XBOX360_VENDOR(0x12ab),            /* X-Box 360 dance pads */
        XPAD_XBOX360_VENDOR(0x1430),            /* RedOctane X-Box 360 controllers */
index 4713957..a878351 100644 (file)
@@ -420,7 +420,7 @@ config KEYBOARD_MPR121
 
 config KEYBOARD_SNVS_PWRKEY
        tristate "IMX SNVS Power Key Driver"
-       depends on SOC_IMX6SX
+       depends on SOC_IMX6SX || SOC_IMX7D
        depends on OF
        help
          This is the snvs powerkey driver for the Freescale i.MX application
index 312916f..73686c2 100644 (file)
@@ -75,9 +75,7 @@
 struct cap11xx_led {
        struct cap11xx_priv *priv;
        struct led_classdev cdev;
-       struct work_struct work;
        u32 reg;
-       enum led_brightness new_brightness;
 };
 #endif
 
@@ -233,30 +231,21 @@ static void cap11xx_input_close(struct input_dev *idev)
 }
 
 #ifdef CONFIG_LEDS_CLASS
-static void cap11xx_led_work(struct work_struct *work)
+static int cap11xx_led_set(struct led_classdev *cdev,
+                           enum led_brightness value)
 {
-       struct cap11xx_led *led = container_of(work, struct cap11xx_led, work);
+       struct cap11xx_led *led = container_of(cdev, struct cap11xx_led, cdev);
        struct cap11xx_priv *priv = led->priv;
-       int value = led->new_brightness;
 
        /*
-        * All LEDs share the same duty cycle as this is a HW limitation.
-        * Brightness levels per LED are either 0 (OFF) and 1 (ON).
+        * All LEDs share the same duty cycle as this is a HW
+        * limitation. Brightness levels per LED are either
+        * 0 (OFF) and 1 (ON).
         */
-       regmap_update_bits(priv->regmap, CAP11XX_REG_LED_OUTPUT_CONTROL,
-                               BIT(led->reg), value ? BIT(led->reg) : 0);
-}
-
-static void cap11xx_led_set(struct led_classdev *cdev,
-                          enum led_brightness value)
-{
-       struct cap11xx_led *led = container_of(cdev, struct cap11xx_led, cdev);
-
-       if (led->new_brightness == value)
-               return;
-
-       led->new_brightness = value;
-       schedule_work(&led->work);
+       return regmap_update_bits(priv->regmap,
+                                 CAP11XX_REG_LED_OUTPUT_CONTROL,
+                                 BIT(led->reg),
+                                 value ? BIT(led->reg) : 0);
 }
 
 static int cap11xx_init_leds(struct device *dev,
@@ -299,7 +288,7 @@ static int cap11xx_init_leds(struct device *dev,
                led->cdev.default_trigger =
                        of_get_property(child, "linux,default-trigger", NULL);
                led->cdev.flags = 0;
-               led->cdev.brightness_set = cap11xx_led_set;
+               led->cdev.brightness_set_blocking = cap11xx_led_set;
                led->cdev.max_brightness = 1;
                led->cdev.brightness = LED_OFF;
 
@@ -312,8 +301,6 @@ static int cap11xx_init_leds(struct device *dev,
                led->reg = reg;
                led->priv = priv;
 
-               INIT_WORK(&led->work, cap11xx_led_work);
-
                error = devm_led_classdev_register(dev, &led->cdev);
                if (error) {
                        of_node_put(child);
index 403452e..3d1cb7b 100644 (file)
@@ -222,7 +222,7 @@ static void matrix_keypad_stop(struct input_dev *dev)
        keypad->stopped = true;
        spin_unlock_irq(&keypad->lock);
 
-       flush_work(&keypad->work.work);
+       flush_delayed_work(&keypad->work);
        /*
         * matrix_keypad_scan() will leave IRQs enabled;
         * we should disable them now.
index 43b8648..d466bc0 100644 (file)
@@ -58,10 +58,9 @@ static unsigned char qt2160_key2code[] = {
 struct qt2160_led {
        struct qt2160_data *qt2160;
        struct led_classdev cdev;
-       struct work_struct work;
        char name[32];
        int id;
-       enum led_brightness new_brightness;
+       enum led_brightness brightness;
 };
 #endif
 
@@ -74,7 +73,6 @@ struct qt2160_data {
        u16 key_matrix;
 #ifdef CONFIG_LEDS_CLASS
        struct qt2160_led leds[QT2160_NUM_LEDS_X];
-       struct mutex led_lock;
 #endif
 };
 
@@ -83,46 +81,39 @@ static int qt2160_write(struct i2c_client *client, u8 reg, u8 data);
 
 #ifdef CONFIG_LEDS_CLASS
 
-static void qt2160_led_work(struct work_struct *work)
+static int qt2160_led_set(struct led_classdev *cdev,
+                         enum led_brightness value)
 {
-       struct qt2160_led *led = container_of(work, struct qt2160_led, work);
+       struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev);
        struct qt2160_data *qt2160 = led->qt2160;
        struct i2c_client *client = qt2160->client;
-       int value = led->new_brightness;
        u32 drive, pwmen;
 
-       mutex_lock(&qt2160->led_lock);
-
-       drive = qt2160_read(client, QT2160_CMD_DRIVE_X);
-       pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X);
-       if (value != LED_OFF) {
-               drive |= (1 << led->id);
-               pwmen |= (1 << led->id);
-
-       } else {
-               drive &= ~(1 << led->id);
-               pwmen &= ~(1 << led->id);
-       }
-       qt2160_write(client, QT2160_CMD_DRIVE_X, drive);
-       qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen);
+       if (value != led->brightness) {
+               drive = qt2160_read(client, QT2160_CMD_DRIVE_X);
+               pwmen = qt2160_read(client, QT2160_CMD_PWMEN_X);
+               if (value != LED_OFF) {
+                       drive |= BIT(led->id);
+                       pwmen |= BIT(led->id);
 
-       /*
-        * Changing this register will change the brightness
-        * of every LED in the qt2160. It's a HW limitation.
-        */
-       if (value != LED_OFF)
-               qt2160_write(client, QT2160_CMD_PWM_DUTY, value);
+               } else {
+                       drive &= ~BIT(led->id);
+                       pwmen &= ~BIT(led->id);
+               }
+               qt2160_write(client, QT2160_CMD_DRIVE_X, drive);
+               qt2160_write(client, QT2160_CMD_PWMEN_X, pwmen);
 
-       mutex_unlock(&qt2160->led_lock);
-}
+               /*
+                * Changing this register will change the brightness
+                * of every LED in the qt2160. It's a HW limitation.
+                */
+               if (value != LED_OFF)
+                       qt2160_write(client, QT2160_CMD_PWM_DUTY, value);
 
-static void qt2160_led_set(struct led_classdev *cdev,
-                          enum led_brightness value)
-{
-       struct qt2160_led *led = container_of(cdev, struct qt2160_led, cdev);
+               led->brightness = value;
+       }
 
-       led->new_brightness = value;
-       schedule_work(&led->work);
+       return 0;
 }
 
 #endif /* CONFIG_LEDS_CLASS */
@@ -293,20 +284,16 @@ static int qt2160_register_leds(struct qt2160_data *qt2160)
        int ret;
        int i;
 
-       mutex_init(&qt2160->led_lock);
-
        for (i = 0; i < QT2160_NUM_LEDS_X; i++) {
                struct qt2160_led *led = &qt2160->leds[i];
 
                snprintf(led->name, sizeof(led->name), "qt2160:x%d", i);
                led->cdev.name = led->name;
-               led->cdev.brightness_set = qt2160_led_set;
+               led->cdev.brightness_set_blocking = qt2160_led_set;
                led->cdev.brightness = LED_OFF;
                led->id = i;
                led->qt2160 = qt2160;
 
-               INIT_WORK(&led->work, qt2160_led_work);
-
                ret = led_classdev_register(&client->dev, &led->cdev);
                if (ret < 0)
                        return ret;
@@ -324,10 +311,8 @@ static void qt2160_unregister_leds(struct qt2160_data *qt2160)
 {
        int i;
 
-       for (i = 0; i < QT2160_NUM_LEDS_X; i++) {
+       for (i = 0; i < QT2160_NUM_LEDS_X; i++)
                led_classdev_unregister(&qt2160->leds[i].cdev);
-               cancel_work_sync(&qt2160->leds[i].work);
-       }
 }
 
 #else
index babcfb1..3b85631 100644 (file)
@@ -153,6 +153,8 @@ static int keyscan_probe(struct platform_device *pdev)
 
        input_dev->id.bustype = BUS_HOST;
 
+       keypad_data->input_dev = input_dev;
+
        error = keypad_matrix_key_parse_dt(keypad_data);
        if (error)
                return error;
@@ -168,8 +170,6 @@ static int keyscan_probe(struct platform_device *pdev)
 
        input_set_drvdata(input_dev, keypad_data);
 
-       keypad_data->input_dev = input_dev;
-
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        keypad_data->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(keypad_data->base))
index 094bddf..c1e66f4 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/io.h>
 #include <linux/input-polldev.h>
 #include <linux/i2c.h>
-#include <linux/workqueue.h>
 #include <linux/leds.h>
 
 #define APANEL_NAME    "Fujitsu Application Panel"
@@ -59,8 +58,6 @@ struct apanel {
        struct i2c_client *client;
        unsigned short keymap[MAX_PANEL_KEYS];
        u16    nkeys;
-       u16    led_bits;
-       struct work_struct led_work;
        struct led_classdev mail_led;
 };
 
@@ -109,25 +106,13 @@ static void apanel_poll(struct input_polled_dev *ipdev)
                        report_key(idev, ap->keymap[i]);
 }
 
-/* Track state changes of LED */
-static void led_update(struct work_struct *work)
-{
-       struct apanel *ap = container_of(work, struct apanel, led_work);
-
-       i2c_smbus_write_word_data(ap->client, 0x10, ap->led_bits);
-}
-
-static void mail_led_set(struct led_classdev *led,
+static int mail_led_set(struct led_classdev *led,
                         enum led_brightness value)
 {
        struct apanel *ap = container_of(led, struct apanel, mail_led);
+       u16 led_bits = value != LED_OFF ? 0x8000 : 0x0000;
 
-       if (value != LED_OFF)
-               ap->led_bits |= 0x8000;
-       else
-               ap->led_bits &= ~0x8000;
-
-       schedule_work(&ap->led_work);
+       return i2c_smbus_write_word_data(ap->client, 0x10, led_bits);
 }
 
 static int apanel_remove(struct i2c_client *client)
@@ -179,7 +164,7 @@ static struct apanel apanel = {
        },
        .mail_led = {
                .name = "mail:blue",
-               .brightness_set = mail_led_set,
+               .brightness_set_blocking = mail_led_set,
        },
 };
 
@@ -235,7 +220,6 @@ static int apanel_probe(struct i2c_client *client,
        if (err)
                goto out3;
 
-       INIT_WORK(&ap->led_work, led_update);
        if (device_chip[APANEL_DEV_LED] != CHIP_NONE) {
                err = led_classdev_register(&client->dev, &ap->mail_led);
                if (err)
index 1efcfdf..dd9dd4e 100644 (file)
@@ -481,13 +481,14 @@ static int bma150_register_input_device(struct bma150_data *bma150)
        idev->close = bma150_irq_close;
        input_set_drvdata(idev, bma150);
 
+       bma150->input = idev;
+
        error = input_register_device(idev);
        if (error) {
                input_free_device(idev);
                return error;
        }
 
-       bma150->input = idev;
        return 0;
 }
 
@@ -510,15 +511,15 @@ static int bma150_register_polled_device(struct bma150_data *bma150)
 
        bma150_init_input_device(bma150, ipoll_dev->input);
 
+       bma150->input_polled = ipoll_dev;
+       bma150->input = ipoll_dev->input;
+
        error = input_register_polled_device(ipoll_dev);
        if (error) {
                input_free_polled_device(ipoll_dev);
                return error;
        }
 
-       bma150->input_polled = ipoll_dev;
-       bma150->input = ipoll_dev->input;
-
        return 0;
 }
 
index 55da191..dbb6d9e 100644 (file)
@@ -34,6 +34,7 @@ struct pwm_vibrator {
        struct work_struct play_work;
        u16 level;
        u32 direction_duty_cycle;
+       bool vcc_on;
 };
 
 static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
@@ -42,10 +43,13 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
        struct pwm_state state;
        int err;
 
-       err = regulator_enable(vibrator->vcc);
-       if (err) {
-               dev_err(pdev, "failed to enable regulator: %d", err);
-               return err;
+       if (!vibrator->vcc_on) {
+               err = regulator_enable(vibrator->vcc);
+               if (err) {
+                       dev_err(pdev, "failed to enable regulator: %d", err);
+                       return err;
+               }
+               vibrator->vcc_on = true;
        }
 
        pwm_get_state(vibrator->pwm, &state);
@@ -76,11 +80,14 @@ static int pwm_vibrator_start(struct pwm_vibrator *vibrator)
 
 static void pwm_vibrator_stop(struct pwm_vibrator *vibrator)
 {
-       regulator_disable(vibrator->vcc);
-
        if (vibrator->pwm_dir)
                pwm_disable(vibrator->pwm_dir);
        pwm_disable(vibrator->pwm);
+
+       if (vibrator->vcc_on) {
+               regulator_disable(vibrator->vcc);
+               vibrator->vcc_on = false;
+       }
 }
 
 static void pwm_vibrator_play_work(struct work_struct *work)
index 8ec483e..26ec603 100644 (file)
@@ -39,6 +39,7 @@
 #include <linux/init.h>
 #include <linux/fs.h>
 #include <linux/miscdevice.h>
+#include <linux/overflow.h>
 #include <linux/input/mt.h>
 #include "../input-compat.h"
 
@@ -405,7 +406,7 @@ static int uinput_open(struct inode *inode, struct file *file)
 static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code,
                                   const struct input_absinfo *abs)
 {
-       int min, max;
+       int min, max, range;
 
        min = abs->minimum;
        max = abs->maximum;
@@ -417,7 +418,7 @@ static int uinput_validate_absinfo(struct input_dev *dev, unsigned int code,
                return -EINVAL;
        }
 
-       if (abs->flat > max - min) {
+       if (!check_sub_overflow(max, min, &range) && abs->flat > range) {
                printk(KERN_DEBUG
                       "%s: abs_flat #%02x out of range: %d (min:%d/max:%d)\n",
                       UINPUT_NAME, code, abs->flat, min, max);
index f322a17..225ae69 100644 (file)
@@ -1336,7 +1336,6 @@ MODULE_DEVICE_TABLE(i2c, elan_id);
 static const struct acpi_device_id elan_acpi_id[] = {
        { "ELAN0000", 0 },
        { "ELAN0100", 0 },
-       { "ELAN0501", 0 },
        { "ELAN0600", 0 },
        { "ELAN0602", 0 },
        { "ELAN0605", 0 },
@@ -1346,6 +1345,7 @@ static const struct acpi_device_id elan_acpi_id[] = {
        { "ELAN060C", 0 },
        { "ELAN0611", 0 },
        { "ELAN0612", 0 },
+       { "ELAN0617", 0 },
        { "ELAN0618", 0 },
        { "ELAN061C", 0 },
        { "ELAN061D", 0 },
index 9fe075c..a7f8b16 100644 (file)
@@ -1119,6 +1119,8 @@ static int elantech_get_resolution_v4(struct psmouse *psmouse,
  * Asus UX31               0x361f00        20, 15, 0e      clickpad
  * Asus UX32VD             0x361f02        00, 15, 0e      clickpad
  * Avatar AVIU-145A2       0x361f00        ?               clickpad
+ * Fujitsu CELSIUS H760    0x570f02        40, 14, 0c      3 hw buttons (**)
+ * Fujitsu CELSIUS H780    0x5d0f02        41, 16, 0d      3 hw buttons (**)
  * Fujitsu LIFEBOOK E544   0x470f00        d0, 12, 09      2 hw buttons
  * Fujitsu LIFEBOOK E546   0x470f00        50, 12, 09      2 hw buttons
  * Fujitsu LIFEBOOK E547   0x470f00        50, 12, 09      2 hw buttons
@@ -1171,6 +1173,13 @@ static const struct dmi_system_id elantech_dmi_has_middle_button[] = {
                        DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H760"),
                },
        },
+       {
+               /* Fujitsu H780 also has a middle button */
+               .matches = {
+                       DMI_MATCH(DMI_SYS_VENDOR, "FUJITSU"),
+                       DMI_MATCH(DMI_PRODUCT_NAME, "CELSIUS H780"),
+               },
+       },
 #endif
        { }
 };
index b360847..a7cfab3 100644 (file)
@@ -23,7 +23,6 @@
 #include <linux/of.h>
 #include <linux/slab.h>
 #include <linux/delay.h>
-#include <linux/clk.h>
 
 /*
  * The OLPC XO-1.75 and XO-4 laptops do not have a hardware PS/2 controller.
@@ -75,7 +74,6 @@ struct olpc_apsp {
        struct serio *kbio;
        struct serio *padio;
        void __iomem *base;
-       struct clk *clk;
        int open_count;
        int irq;
 };
@@ -148,17 +146,11 @@ static int olpc_apsp_open(struct serio *port)
        struct olpc_apsp *priv = port->port_data;
        unsigned int tmp;
        unsigned long l;
-       int error;
 
        if (priv->open_count++ == 0) {
-               error = clk_prepare_enable(priv->clk);
-               if (error)
-                       return error;
-
                l = readl(priv->base + COMMAND_FIFO_STATUS);
                if (!(l & CMD_STS_MASK)) {
                        dev_err(priv->dev, "SP cannot accept commands.\n");
-                       clk_disable_unprepare(priv->clk);
                        return -EIO;
                }
 
@@ -179,8 +171,6 @@ static void olpc_apsp_close(struct serio *port)
                /* Disable interrupt 0 */
                tmp = readl(priv->base + PJ_INTERRUPT_MASK);
                writel(tmp | INT_0, priv->base + PJ_INTERRUPT_MASK);
-
-               clk_disable_unprepare(priv->clk);
        }
 }
 
@@ -195,6 +185,8 @@ static int olpc_apsp_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
+       priv->dev = &pdev->dev;
+
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        priv->base = devm_ioremap_resource(&pdev->dev, res);
        if (IS_ERR(priv->base)) {
@@ -206,10 +198,6 @@ static int olpc_apsp_probe(struct platform_device *pdev)
        if (priv->irq < 0)
                return priv->irq;
 
-       priv->clk = devm_clk_get(&pdev->dev, "sp");
-       if (IS_ERR(priv->clk))
-               return PTR_ERR(priv->clk);
-
        /* KEYBOARD */
        kb_serio = kzalloc(sizeof(struct serio), GFP_KERNEL);
        if (!kb_serio)
@@ -248,7 +236,6 @@ static int olpc_apsp_probe(struct platform_device *pdev)
                goto err_irq;
        }
 
-       priv->dev = &pdev->dev;
        device_init_wakeup(priv->dev, 1);
        platform_set_drvdata(pdev, priv);
 
index c62cceb..5e8d838 100644 (file)
@@ -76,6 +76,7 @@ static void ps2_gpio_close(struct serio *serio)
 {
        struct ps2_gpio_data *drvdata = serio->port_data;
 
+       flush_delayed_work(&drvdata->tx_work);
        disable_irq(drvdata->irq);
 }
 
index af6027c..068dbbc 100644 (file)
@@ -698,7 +698,7 @@ config TOUCHSCREEN_EDT_FT5X06
 
 config TOUCHSCREEN_RASPBERRYPI_FW
        tristate "Raspberry Pi's firmware base touch screen support"
-       depends on RASPBERRYPI_FIRMWARE || COMPILE_TEST
+       depends on RASPBERRYPI_FIRMWARE || (RASPBERRYPI_FIRMWARE=n && COMPILE_TEST)
        help
          Say Y here if you have the official Raspberry Pi 7 inch screen on
          your system.
index f456c11..6988126 100644 (file)
@@ -147,8 +147,8 @@ static int rpi_ts_probe(struct platform_device *pdev)
                return -ENOMEM;
        ts->pdev = pdev;
 
-       ts->fw_regs_va = dma_zalloc_coherent(dev, PAGE_SIZE, &ts->fw_regs_phys,
-                                            GFP_KERNEL);
+       ts->fw_regs_va = dma_alloc_coherent(dev, PAGE_SIZE, &ts->fw_regs_phys,
+                                           GFP_KERNEL);
        if (!ts->fw_regs_va) {
                dev_err(dev, "failed to dma_alloc_coherent\n");
                return -ENOMEM;
index 87ba23a..2a7b78b 100644 (file)
@@ -1991,16 +1991,13 @@ static void do_attach(struct iommu_dev_data *dev_data,
 
 static void do_detach(struct iommu_dev_data *dev_data)
 {
+       struct protection_domain *domain = dev_data->domain;
        struct amd_iommu *iommu;
        u16 alias;
 
        iommu = amd_iommu_rlookup_table[dev_data->devid];
        alias = dev_data->alias;
 
-       /* decrease reference counters */
-       dev_data->domain->dev_iommu[iommu->index] -= 1;
-       dev_data->domain->dev_cnt                 -= 1;
-
        /* Update data structures */
        dev_data->domain = NULL;
        list_del(&dev_data->list);
@@ -2010,6 +2007,16 @@ static void do_detach(struct iommu_dev_data *dev_data)
 
        /* Flush the DTE entry */
        device_flush_dte(dev_data);
+
+       /* Flush IOTLB */
+       domain_flush_tlb_pde(domain);
+
+       /* Wait for the flushes to finish */
+       domain_flush_complete(domain);
+
+       /* decrease reference counters - needs to happen after the flushes */
+       domain->dev_iommu[iommu->index] -= 1;
+       domain->dev_cnt                 -= 1;
 }
 
 /*
@@ -2617,13 +2624,13 @@ out_unmap:
                        bus_addr  = address + s->dma_address + (j << PAGE_SHIFT);
                        iommu_unmap_page(domain, bus_addr, PAGE_SIZE);
 
-                       if (--mapped_pages)
+                       if (--mapped_pages == 0)
                                goto out_free_iova;
                }
        }
 
 out_free_iova:
-       free_iova_fast(&dma_dom->iovad, address, npages);
+       free_iova_fast(&dma_dom->iovad, address >> PAGE_SHIFT, npages);
 
 out_err:
        return 0;
index 2bd9ac2..78188bf 100644 (file)
@@ -363,7 +363,7 @@ static int dmar_map_gfx = 1;
 static int dmar_forcedac;
 static int intel_iommu_strict;
 static int intel_iommu_superpage = 1;
-static int intel_iommu_sm = 1;
+static int intel_iommu_sm;
 static int iommu_identity_mapping;
 
 #define IDENTMAP_ALL           1
@@ -456,9 +456,9 @@ static int __init intel_iommu_setup(char *str)
                } else if (!strncmp(str, "sp_off", 6)) {
                        pr_info("Disable supported super page\n");
                        intel_iommu_superpage = 0;
-               } else if (!strncmp(str, "sm_off", 6)) {
-                       pr_info("Intel-IOMMU: disable scalable mode support\n");
-                       intel_iommu_sm = 0;
+               } else if (!strncmp(str, "sm_on", 5)) {
+                       pr_info("Intel-IOMMU: scalable mode supported\n");
+                       intel_iommu_sm = 1;
                } else if (!strncmp(str, "tboot_noforce", 13)) {
                        printk(KERN_INFO
                                "Intel-IOMMU: not forcing on after tboot. This could expose security risk for tboot\n");
@@ -5294,7 +5294,7 @@ static void intel_iommu_put_resv_regions(struct device *dev,
        struct iommu_resv_region *entry, *next;
 
        list_for_each_entry_safe(entry, next, head, list) {
-               if (entry->type == IOMMU_RESV_RESERVED)
+               if (entry->type == IOMMU_RESV_MSI)
                        kfree(entry);
        }
 }
index 6ede428..7e0df67 100644 (file)
@@ -232,9 +232,8 @@ static int mtk_iommu_domain_finalise(struct mtk_iommu_data *data)
 
        spin_lock_init(&dom->pgtlock);
 
-       dom->pgt_va = dma_zalloc_coherent(data->dev,
-                               M2701_IOMMU_PGT_SIZE,
-                               &dom->pgt_pa, GFP_KERNEL);
+       dom->pgt_va = dma_alloc_coherent(data->dev, M2701_IOMMU_PGT_SIZE,
+                                        &dom->pgt_pa, GFP_KERNEL);
        if (!dom->pgt_va)
                return -ENOMEM;
 
@@ -442,6 +441,10 @@ static int mtk_iommu_add_device(struct device *dev)
                iommu_spec.args_count = count;
 
                mtk_iommu_create_mapping(dev, &iommu_spec);
+
+               /* dev->iommu_fwspec might have changed */
+               fwspec = dev_iommu_fwspec_get(dev);
+
                of_node_put(iommu_spec.np);
        }
 
index d8947b2..f04a6df 100644 (file)
@@ -224,7 +224,7 @@ const struct iommu_ops *of_iommu_configure(struct device *dev,
         * If we have reason to believe the IOMMU driver missed the initial
         * probe for dev, replay it to get things in order.
         */
-       if (dev->bus && !device_iommu_mapped(dev))
+       if (!err && dev->bus && !device_iommu_mapped(dev))
                err = iommu_probe_device(dev);
 
        /* Ignore all other errors apart from EPROBE_DEFER */
index 2543bab..5a2ec43 100644 (file)
@@ -95,7 +95,7 @@ static inline void setup_irq_channel(u32 magic, void __iomem *reg_addr)
 
        /* Setup 64 channel slots */
        for (i = 0; i < INTC_IRQS; i += 4)
-               writel_relaxed(build_channel_val(i, magic), reg_addr + i);
+               writel(build_channel_val(i, magic), reg_addr + i);
 }
 
 static int __init
@@ -135,16 +135,10 @@ ck_intc_init_comm(struct device_node *node, struct device_node *parent)
 static inline bool handle_irq_perbit(struct pt_regs *regs, u32 hwirq,
                                     u32 irq_base)
 {
-       u32 irq;
-
        if (hwirq == 0)
                return 0;
 
-       while (hwirq) {
-               irq = __ffs(hwirq);
-               hwirq &= ~BIT(irq);
-               handle_domain_irq(root_domain, irq_base + irq, regs);
-       }
+       handle_domain_irq(root_domain, irq_base + __fls(hwirq), regs);
 
        return 1;
 }
@@ -154,12 +148,16 @@ static void gx_irq_handler(struct pt_regs *regs)
 {
        bool ret;
 
-       do {
-               ret  = handle_irq_perbit(regs,
-                               readl_relaxed(reg_base + GX_INTC_PEN31_00), 0);
-               ret |= handle_irq_perbit(regs,
-                               readl_relaxed(reg_base + GX_INTC_PEN63_32), 32);
-       } while (ret);
+retry:
+       ret = handle_irq_perbit(regs,
+                       readl(reg_base + GX_INTC_PEN63_32), 32);
+       if (ret)
+               goto retry;
+
+       ret = handle_irq_perbit(regs,
+                       readl(reg_base + GX_INTC_PEN31_00), 0);
+       if (ret)
+               goto retry;
 }
 
 static int __init
@@ -174,14 +172,14 @@ gx_intc_init(struct device_node *node, struct device_node *parent)
        /*
         * Initial enable reg to disable all interrupts
         */
-       writel_relaxed(0x0, reg_base + GX_INTC_NEN31_00);
-       writel_relaxed(0x0, reg_base + GX_INTC_NEN63_32);
+       writel(0x0, reg_base + GX_INTC_NEN31_00);
+       writel(0x0, reg_base + GX_INTC_NEN63_32);
 
        /*
         * Initial mask reg with all unmasked, because we only use enalbe reg
         */
-       writel_relaxed(0x0, reg_base + GX_INTC_NMASK31_00);
-       writel_relaxed(0x0, reg_base + GX_INTC_NMASK63_32);
+       writel(0x0, reg_base + GX_INTC_NMASK31_00);
+       writel(0x0, reg_base + GX_INTC_NMASK63_32);
 
        setup_irq_channel(0x03020100, reg_base + GX_INTC_SOURCE);
 
@@ -204,20 +202,29 @@ static void ck_irq_handler(struct pt_regs *regs)
        void __iomem *reg_pen_lo = reg_base + CK_INTC_PEN31_00;
        void __iomem *reg_pen_hi = reg_base + CK_INTC_PEN63_32;
 
-       do {
-               /* handle 0 - 31 irqs */
-               ret  = handle_irq_perbit(regs, readl_relaxed(reg_pen_lo), 0);
-               ret |= handle_irq_perbit(regs, readl_relaxed(reg_pen_hi), 32);
+retry:
+       /* handle 0 - 63 irqs */
+       ret = handle_irq_perbit(regs, readl(reg_pen_hi), 32);
+       if (ret)
+               goto retry;
 
-               if (nr_irq == INTC_IRQS)
-                       continue;
+       ret = handle_irq_perbit(regs, readl(reg_pen_lo), 0);
+       if (ret)
+               goto retry;
+
+       if (nr_irq == INTC_IRQS)
+               return;
 
-               /* handle 64 - 127 irqs */
-               ret |= handle_irq_perbit(regs,
-                       readl_relaxed(reg_pen_lo + CK_INTC_DUAL_BASE), 64);
-               ret |= handle_irq_perbit(regs,
-                       readl_relaxed(reg_pen_hi + CK_INTC_DUAL_BASE), 96);
-       } while (ret);
+       /* handle 64 - 127 irqs */
+       ret = handle_irq_perbit(regs,
+                       readl(reg_pen_hi + CK_INTC_DUAL_BASE), 96);
+       if (ret)
+               goto retry;
+
+       ret = handle_irq_perbit(regs,
+                       readl(reg_pen_lo + CK_INTC_DUAL_BASE), 64);
+       if (ret)
+               goto retry;
 }
 
 static int __init
@@ -230,11 +237,11 @@ ck_intc_init(struct device_node *node, struct device_node *parent)
                return ret;
 
        /* Initial enable reg to disable all interrupts */
-       writel_relaxed(0, reg_base + CK_INTC_NEN31_00);
-       writel_relaxed(0, reg_base + CK_INTC_NEN63_32);
+       writel(0, reg_base + CK_INTC_NEN31_00);
+       writel(0, reg_base + CK_INTC_NEN63_32);
 
        /* Enable irq intc */
-       writel_relaxed(BIT(31), reg_base + CK_INTC_ICR);
+       writel(BIT(31), reg_base + CK_INTC_ICR);
 
        ck_set_gc(node, reg_base, CK_INTC_NEN31_00, 0);
        ck_set_gc(node, reg_base, CK_INTC_NEN63_32, 32);
@@ -260,8 +267,8 @@ ck_dual_intc_init(struct device_node *node, struct device_node *parent)
                return ret;
 
        /* Initial enable reg to disable all interrupts */
-       writel_relaxed(0, reg_base + CK_INTC_NEN31_00 + CK_INTC_DUAL_BASE);
-       writel_relaxed(0, reg_base + CK_INTC_NEN63_32 + CK_INTC_DUAL_BASE);
+       writel(0, reg_base + CK_INTC_NEN31_00 + CK_INTC_DUAL_BASE);
+       writel(0, reg_base + CK_INTC_NEN63_32 + CK_INTC_DUAL_BASE);
 
        ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN31_00, 64);
        ck_set_gc(node, reg_base + CK_INTC_DUAL_BASE, CK_INTC_NEN63_32, 96);
index db20e99..c3aba3f 100644 (file)
@@ -97,9 +97,14 @@ struct its_device;
  * The ITS structure - contains most of the infrastructure, with the
  * top-level MSI domain, the command queue, the collections, and the
  * list of devices writing to it.
+ *
+ * dev_alloc_lock has to be taken for device allocations, while the
+ * spinlock must be taken to parse data structures such as the device
+ * list.
  */
 struct its_node {
        raw_spinlock_t          lock;
+       struct mutex            dev_alloc_lock;
        struct list_head        entry;
        void __iomem            *base;
        phys_addr_t             phys_base;
@@ -156,6 +161,7 @@ struct its_device {
        void                    *itt;
        u32                     nr_ites;
        u32                     device_id;
+       bool                    shared;
 };
 
 static struct {
@@ -1580,6 +1586,9 @@ static unsigned long *its_lpi_alloc(int nr_irqs, u32 *base, int *nr_ids)
                nr_irqs /= 2;
        } while (nr_irqs > 0);
 
+       if (!nr_irqs)
+               err = -ENOSPC;
+
        if (err)
                goto out;
 
@@ -2059,6 +2068,29 @@ static int __init allocate_lpi_tables(void)
        return 0;
 }
 
+static u64 its_clear_vpend_valid(void __iomem *vlpi_base)
+{
+       u32 count = 1000000;    /* 1s! */
+       bool clean;
+       u64 val;
+
+       val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
+       val &= ~GICR_VPENDBASER_Valid;
+       gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
+
+       do {
+               val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
+               clean = !(val & GICR_VPENDBASER_Dirty);
+               if (!clean) {
+                       count--;
+                       cpu_relax();
+                       udelay(1);
+               }
+       } while (!clean && count);
+
+       return val;
+}
+
 static void its_cpu_init_lpis(void)
 {
        void __iomem *rbase = gic_data_rdist_rd_base();
@@ -2144,6 +2176,30 @@ static void its_cpu_init_lpis(void)
        val |= GICR_CTLR_ENABLE_LPIS;
        writel_relaxed(val, rbase + GICR_CTLR);
 
+       if (gic_rdists->has_vlpis) {
+               void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
+
+               /*
+                * It's possible for CPU to receive VLPIs before it is
+                * sheduled as a vPE, especially for the first CPU, and the
+                * VLPI with INTID larger than 2^(IDbits+1) will be considered
+                * as out of range and dropped by GIC.
+                * So we initialize IDbits to known value to avoid VLPI drop.
+                */
+               val = (LPI_NRBITS - 1) & GICR_VPROPBASER_IDBITS_MASK;
+               pr_debug("GICv4: CPU%d: Init IDbits to 0x%llx for GICR_VPROPBASER\n",
+                       smp_processor_id(), val);
+               gits_write_vpropbaser(val, vlpi_base + GICR_VPROPBASER);
+
+               /*
+                * Also clear Valid bit of GICR_VPENDBASER, in case some
+                * ancient programming gets left in and has possibility of
+                * corrupting memory.
+                */
+               val = its_clear_vpend_valid(vlpi_base);
+               WARN_ON(val & GICR_VPENDBASER_Dirty);
+       }
+
        /* Make sure the GIC has seen the above */
        dsb(sy);
 out:
@@ -2399,13 +2455,14 @@ static void its_free_device(struct its_device *its_dev)
        kfree(its_dev);
 }
 
-static int its_alloc_device_irq(struct its_device *dev, irq_hw_number_t *hwirq)
+static int its_alloc_device_irq(struct its_device *dev, int nvecs, irq_hw_number_t *hwirq)
 {
        int idx;
 
-       idx = find_first_zero_bit(dev->event_map.lpi_map,
-                                 dev->event_map.nr_lpis);
-       if (idx == dev->event_map.nr_lpis)
+       idx = bitmap_find_free_region(dev->event_map.lpi_map,
+                                     dev->event_map.nr_lpis,
+                                     get_count_order(nvecs));
+       if (idx < 0)
                return -ENOSPC;
 
        *hwirq = dev->event_map.lpi_base + idx;
@@ -2421,6 +2478,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
        struct its_device *its_dev;
        struct msi_domain_info *msi_info;
        u32 dev_id;
+       int err = 0;
 
        /*
         * We ignore "dev" entierely, and rely on the dev_id that has
@@ -2443,6 +2501,7 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
                return -EINVAL;
        }
 
+       mutex_lock(&its->dev_alloc_lock);
        its_dev = its_find_device(its, dev_id);
        if (its_dev) {
                /*
@@ -2450,18 +2509,22 @@ static int its_msi_prepare(struct irq_domain *domain, struct device *dev,
                 * another alias (PCI bridge of some sort). No need to
                 * create the device.
                 */
+               its_dev->shared = true;
                pr_debug("Reusing ITT for devID %x\n", dev_id);
                goto out;
        }
 
        its_dev = its_create_device(its, dev_id, nvec, true);
-       if (!its_dev)
-               return -ENOMEM;
+       if (!its_dev) {
+               err = -ENOMEM;
+               goto out;
+       }
 
        pr_debug("ITT %d entries, %d bits\n", nvec, ilog2(nvec));
 out:
+       mutex_unlock(&its->dev_alloc_lock);
        info->scratchpad[0].ptr = its_dev;
-       return 0;
+       return err;
 }
 
 static struct msi_domain_ops its_msi_domain_ops = {
@@ -2501,21 +2564,21 @@ static int its_irq_domain_alloc(struct irq_domain *domain, unsigned int virq,
        int err;
        int i;
 
-       for (i = 0; i < nr_irqs; i++) {
-               err = its_alloc_device_irq(its_dev, &hwirq);
-               if (err)
-                       return err;
+       err = its_alloc_device_irq(its_dev, nr_irqs, &hwirq);
+       if (err)
+               return err;
 
-               err = its_irq_gic_domain_alloc(domain, virq + i, hwirq);
+       for (i = 0; i < nr_irqs; i++) {
+               err = its_irq_gic_domain_alloc(domain, virq + i, hwirq + i);
                if (err)
                        return err;
 
                irq_domain_set_hwirq_and_chip(domain, virq + i,
-                                             hwirq, &its_irq_chip, its_dev);
+                                             hwirq + i, &its_irq_chip, its_dev);
                irqd_set_single_target(irq_desc_get_irq_data(irq_to_desc(virq + i)));
                pr_debug("ID:%d pID:%d vID:%d\n",
-                        (int)(hwirq - its_dev->event_map.lpi_base),
-                        (int) hwirq, virq + i);
+                        (int)(hwirq + i - its_dev->event_map.lpi_base),
+                        (int)(hwirq + i), virq + i);
        }
 
        return 0;
@@ -2565,6 +2628,7 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
 {
        struct irq_data *d = irq_domain_get_irq_data(domain, virq);
        struct its_device *its_dev = irq_data_get_irq_chip_data(d);
+       struct its_node *its = its_dev->its;
        int i;
 
        for (i = 0; i < nr_irqs; i++) {
@@ -2579,8 +2643,14 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
                irq_domain_reset_irq_data(data);
        }
 
-       /* If all interrupts have been freed, start mopping the floor */
-       if (bitmap_empty(its_dev->event_map.lpi_map,
+       mutex_lock(&its->dev_alloc_lock);
+
+       /*
+        * If all interrupts have been freed, start mopping the
+        * floor. This is conditionned on the device not being shared.
+        */
+       if (!its_dev->shared &&
+           bitmap_empty(its_dev->event_map.lpi_map,
                         its_dev->event_map.nr_lpis)) {
                its_lpi_free(its_dev->event_map.lpi_map,
                             its_dev->event_map.lpi_base,
@@ -2592,6 +2662,8 @@ static void its_irq_domain_free(struct irq_domain *domain, unsigned int virq,
                its_free_device(its_dev);
        }
 
+       mutex_unlock(&its->dev_alloc_lock);
+
        irq_domain_free_irqs_parent(domain, virq, nr_irqs);
 }
 
@@ -2754,26 +2826,11 @@ static void its_vpe_schedule(struct its_vpe *vpe)
 static void its_vpe_deschedule(struct its_vpe *vpe)
 {
        void __iomem *vlpi_base = gic_data_rdist_vlpi_base();
-       u32 count = 1000000;    /* 1s! */
-       bool clean;
        u64 val;
 
-       /* We're being scheduled out */
-       val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
-       val &= ~GICR_VPENDBASER_Valid;
-       gits_write_vpendbaser(val, vlpi_base + GICR_VPENDBASER);
-
-       do {
-               val = gits_read_vpendbaser(vlpi_base + GICR_VPENDBASER);
-               clean = !(val & GICR_VPENDBASER_Dirty);
-               if (!clean) {
-                       count--;
-                       cpu_relax();
-                       udelay(1);
-               }
-       } while (!clean && count);
+       val = its_clear_vpend_valid(vlpi_base);
 
-       if (unlikely(!clean && !count)) {
+       if (unlikely(val & GICR_VPENDBASER_Dirty)) {
                pr_err_ratelimited("ITS virtual pending table not cleaning\n");
                vpe->idai = false;
                vpe->pending_last = true;
@@ -3516,6 +3573,7 @@ static int __init its_probe_one(struct resource *res,
        }
 
        raw_spin_lock_init(&its->lock);
+       mutex_init(&its->dev_alloc_lock);
        INIT_LIST_HEAD(&its->entry);
        INIT_LIST_HEAD(&its->its_device_list);
        typer = gic_read_typer(its_base + GITS_TYPER);
index ad70e7c..fbfa7ff 100644 (file)
@@ -24,7 +24,7 @@ struct mbi_range {
        unsigned long           *bm;
 };
 
-static struct mutex            mbi_lock;
+static DEFINE_MUTEX(mbi_lock);
 static phys_addr_t             mbi_phys_base;
 static struct mbi_range                *mbi_ranges;
 static unsigned int            mbi_range_nr;
index e9256de..8b81271 100644 (file)
@@ -7,7 +7,6 @@
  */
 
 #include <linux/module.h>
-#include <linux/gpio.h>
 #include <linux/interrupt.h>
 #include <linux/irq.h>
 #include <linux/irqdomain.h>
@@ -16,7 +15,6 @@
 #include <linux/slab.h>
 #include <linux/of.h>
 #include <linux/of_device.h>
-#include <linux/of_gpio.h>
 #include <linux/of_irq.h>
 #include <linux/irqchip/irq-madera.h>
 #include <linux/mfd/madera/core.h>
index 25f32e1..3496b61 100644 (file)
@@ -34,6 +34,9 @@
 #define SEL_INT_PENDING                (1 << 6)
 #define SEL_INT_NUM_MASK       0x3f
 
+#define MMP2_ICU_INT_ROUTE_PJ4_IRQ     (1 << 5)
+#define MMP2_ICU_INT_ROUTE_PJ4_FIQ     (1 << 6)
+
 struct icu_chip_data {
        int                     nr_irqs;
        unsigned int            virq_base;
@@ -190,7 +193,8 @@ static const struct mmp_intc_conf mmp_conf = {
 static const struct mmp_intc_conf mmp2_conf = {
        .conf_enable    = 0x20,
        .conf_disable   = 0x0,
-       .conf_mask      = 0x7f,
+       .conf_mask      = MMP2_ICU_INT_ROUTE_PJ4_IRQ |
+                         MMP2_ICU_INT_ROUTE_PJ4_FIQ,
 };
 
 static void __exception_irq_entry mmp_handle_irq(struct pt_regs *regs)
index 6edfd4b..a93296b 100644 (file)
@@ -822,6 +822,7 @@ out_unmap:
 static const struct irq_domain_ops stm32_exti_h_domain_ops = {
        .alloc  = stm32_exti_h_domain_alloc,
        .free   = irq_domain_free_irqs_common,
+       .xlate = irq_domain_xlate_twocell,
 };
 
 static int
index 5385f57..2793333 100644 (file)
@@ -71,14 +71,17 @@ static void xtensa_mx_irq_mask(struct irq_data *d)
        unsigned int mask = 1u << d->hwirq;
 
        if (mask & (XCHAL_INTTYPE_MASK_EXTERN_EDGE |
-                               XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
-               set_er(1u << (xtensa_get_ext_irq_no(d->hwirq) -
-                                       HW_IRQ_MX_BASE), MIENG);
-       } else {
-               mask = __this_cpu_read(cached_irq_mask) & ~mask;
-               __this_cpu_write(cached_irq_mask, mask);
-               xtensa_set_sr(mask, intenable);
+                   XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
+               unsigned int ext_irq = xtensa_get_ext_irq_no(d->hwirq);
+
+               if (ext_irq >= HW_IRQ_MX_BASE) {
+                       set_er(1u << (ext_irq - HW_IRQ_MX_BASE), MIENG);
+                       return;
+               }
        }
+       mask = __this_cpu_read(cached_irq_mask) & ~mask;
+       __this_cpu_write(cached_irq_mask, mask);
+       xtensa_set_sr(mask, intenable);
 }
 
 static void xtensa_mx_irq_unmask(struct irq_data *d)
@@ -86,14 +89,17 @@ static void xtensa_mx_irq_unmask(struct irq_data *d)
        unsigned int mask = 1u << d->hwirq;
 
        if (mask & (XCHAL_INTTYPE_MASK_EXTERN_EDGE |
-                               XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
-               set_er(1u << (xtensa_get_ext_irq_no(d->hwirq) -
-                                       HW_IRQ_MX_BASE), MIENGSET);
-       } else {
-               mask |= __this_cpu_read(cached_irq_mask);
-               __this_cpu_write(cached_irq_mask, mask);
-               xtensa_set_sr(mask, intenable);
+                   XCHAL_INTTYPE_MASK_EXTERN_LEVEL)) {
+               unsigned int ext_irq = xtensa_get_ext_irq_no(d->hwirq);
+
+               if (ext_irq >= HW_IRQ_MX_BASE) {
+                       set_er(1u << (ext_irq - HW_IRQ_MX_BASE), MIENGSET);
+                       return;
+               }
        }
+       mask |= __this_cpu_read(cached_irq_mask);
+       __this_cpu_write(cached_irq_mask, mask);
+       xtensa_set_sr(mask, intenable);
 }
 
 static void xtensa_mx_irq_enable(struct irq_data *d)
@@ -113,7 +119,11 @@ static void xtensa_mx_irq_ack(struct irq_data *d)
 
 static int xtensa_mx_irq_retrigger(struct irq_data *d)
 {
-       xtensa_set_sr(1 << d->hwirq, intset);
+       unsigned int mask = 1u << d->hwirq;
+
+       if (WARN_ON(mask & ~XCHAL_INTTYPE_MASK_SOFTWARE))
+               return 0;
+       xtensa_set_sr(mask, intset);
        return 1;
 }
 
index c200234..ab12328 100644 (file)
@@ -70,7 +70,11 @@ static void xtensa_irq_ack(struct irq_data *d)
 
 static int xtensa_irq_retrigger(struct irq_data *d)
 {
-       xtensa_set_sr(1 << d->hwirq, intset);
+       unsigned int mask = 1u << d->hwirq;
+
+       if (WARN_ON(mask & ~XCHAL_INTTYPE_MASK_SOFTWARE))
+               return 0;
+       xtensa_set_sr(mask, intset);
        return 1;
 }
 
index 4ac378e..40ca1e8 100644 (file)
@@ -423,7 +423,7 @@ void b1_parse_version(avmctrl_info *cinfo)
        int i, j;
 
        for (j = 0; j < AVM_MAXVERSION; j++)
-               cinfo->version[j] = "\0\0" + 1;
+               cinfo->version[j] = "";
        for (i = 0, j = 0;
             j < AVM_MAXVERSION && i < cinfo->versionlen;
             j++, i += cinfo->versionbuf[i] + 1)
index 6d05946..124ff53 100644 (file)
@@ -262,8 +262,7 @@ hfcsusb_ph_info(struct hfcsusb *hw)
        struct dchannel *dch = &hw->dch;
        int i;
 
-       phi = kzalloc(sizeof(struct ph_info) +
-                     dch->dev.nrbchan * sizeof(struct ph_info_ch), GFP_ATOMIC);
+       phi = kzalloc(struct_size(phi, bch, dch->dev.nrbchan), GFP_ATOMIC);
        phi->dch.ch.protocol = hw->protocol;
        phi->dch.ch.Flags = dch->Flags;
        phi->dch.state = dch->state;
index 1b2239c..dc1cded 100644 (file)
@@ -1437,15 +1437,19 @@ isdn_tty_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        modem_info *info = (modem_info *) tty->driver_data;
 
+       mutex_lock(&modem_info_mutex);
        if (!old_termios)
                isdn_tty_change_speed(info);
        else {
                if (tty->termios.c_cflag == old_termios->c_cflag &&
                    tty->termios.c_ispeed == old_termios->c_ispeed &&
-                   tty->termios.c_ospeed == old_termios->c_ospeed)
+                   tty->termios.c_ospeed == old_termios->c_ospeed) {
+                       mutex_unlock(&modem_info_mutex);
                        return;
+               }
                isdn_tty_change_speed(info);
        }
+       mutex_unlock(&modem_info_mutex);
 }
 
 /*
index 211ed6c..5789787 100644 (file)
@@ -170,8 +170,8 @@ dev_expire_timer(struct timer_list *t)
        spin_lock_irqsave(&timer->dev->lock, flags);
        if (timer->id >= 0)
                list_move_tail(&timer->list, &timer->dev->expired);
-       spin_unlock_irqrestore(&timer->dev->lock, flags);
        wake_up_interruptible(&timer->dev->wait);
+       spin_unlock_irqrestore(&timer->dev->lock, flags);
 }
 
 static int
index a2e74fe..fd64df5 100644 (file)
@@ -318,7 +318,9 @@ static int lp5523_init_program_engine(struct lp55xx_chip *chip)
 
        /* Let the programs run for couple of ms and check the engine status */
        usleep_range(3000, 6000);
-       lp55xx_read(chip, LP5523_REG_STATUS, &status);
+       ret = lp55xx_read(chip, LP5523_REG_STATUS, &status);
+       if (ret)
+               return ret;
        status &= LP5523_ENG_STATUS_MASK;
 
        if (status != LP5523_ENG_STATUS_MASK) {
index d713271..a641165 100644 (file)
@@ -1396,9 +1396,9 @@ static void flexrm_shutdown(struct mbox_chan *chan)
 
        /* Clear ring flush state */
        timeout = 1000; /* timeout of 1s */
-       writel_relaxed(0x0, ring + RING_CONTROL);
+       writel_relaxed(0x0, ring->regs + RING_CONTROL);
        do {
-               if (!(readl_relaxed(ring + RING_FLUSH_DONE) &
+               if (!(readl_relaxed(ring->regs + RING_FLUSH_DONE) &
                      FLUSH_DONE_MASK))
                        break;
                mdelay(1);
index c6a7d45..38d9df3 100644 (file)
@@ -310,6 +310,7 @@ int mbox_flush(struct mbox_chan *chan, unsigned long timeout)
 
        return ret;
 }
+EXPORT_SYMBOL_GPL(mbox_flush);
 
 /**
  * mbox_request_channel - Request a mailbox channel.
index 0ff2215..dd538e6 100644 (file)
@@ -932,7 +932,7 @@ static int dm_crypt_integrity_io_alloc(struct dm_crypt_io *io, struct bio *bio)
        if (IS_ERR(bip))
                return PTR_ERR(bip);
 
-       tag_len = io->cc->on_disk_tag_size * bio_sectors(bio);
+       tag_len = io->cc->on_disk_tag_size * (bio_sectors(bio) >> io->cc->sector_shift);
 
        bip->bip_iter.bi_size = tag_len;
        bip->bip_iter.bi_sector = io->cc->start + io->sector;
@@ -2414,9 +2414,21 @@ static int crypt_ctr_cipher_new(struct dm_target *ti, char *cipher_in, char *key
         * capi:cipher_api_spec-iv:ivopts
         */
        tmp = &cipher_in[strlen("capi:")];
-       cipher_api = strsep(&tmp, "-");
-       *ivmode = strsep(&tmp, ":");
-       *ivopts = tmp;
+
+       /* Separate IV options if present, it can contain another '-' in hash name */
+       *ivopts = strrchr(tmp, ':');
+       if (*ivopts) {
+               **ivopts = '\0';
+               (*ivopts)++;
+       }
+       /* Parse IV mode */
+       *ivmode = strrchr(tmp, '-');
+       if (*ivmode) {
+               **ivmode = '\0';
+               (*ivmode)++;
+       }
+       /* The rest is crypto API spec */
+       cipher_api = tmp;
 
        if (*ivmode && !strcmp(*ivmode, "lmk"))
                cc->tfms_count = 64;
@@ -2486,11 +2498,8 @@ static int crypt_ctr_cipher_old(struct dm_target *ti, char *cipher_in, char *key
                goto bad_mem;
 
        chainmode = strsep(&tmp, "-");
-       *ivopts = strsep(&tmp, "-");
-       *ivmode = strsep(&*ivopts, ":");
-
-       if (tmp)
-               DMWARN("Ignoring unexpected additional cipher options");
+       *ivmode = strsep(&tmp, ":");
+       *ivopts = tmp;
 
        /*
         * For compatibility with the original dm-crypt mapping format, if
index 4eb5f8c..a20531e 100644 (file)
@@ -131,7 +131,7 @@ static void rq_end_stats(struct mapped_device *md, struct request *orig)
 static void rq_completed(struct mapped_device *md)
 {
        /* nudge anyone waiting on suspend queue */
-       if (unlikely(waitqueue_active(&md->wait)))
+       if (unlikely(wq_has_sleeper(&md->wait)))
                wake_up(&md->wait);
 
        /*
index 20b0776..ed3cace 100644 (file)
@@ -1678,7 +1678,7 @@ int dm_thin_remove_range(struct dm_thin_device *td,
        return r;
 }
 
-int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result)
+int dm_pool_block_is_shared(struct dm_pool_metadata *pmd, dm_block_t b, bool *result)
 {
        int r;
        uint32_t ref_count;
@@ -1686,7 +1686,7 @@ int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *resu
        down_read(&pmd->root_lock);
        r = dm_sm_get_count(pmd->data_sm, b, &ref_count);
        if (!r)
-               *result = (ref_count != 0);
+               *result = (ref_count > 1);
        up_read(&pmd->root_lock);
 
        return r;
index 35e954e..f6be0d7 100644 (file)
@@ -195,7 +195,7 @@ int dm_pool_get_metadata_dev_size(struct dm_pool_metadata *pmd,
 
 int dm_pool_get_data_dev_size(struct dm_pool_metadata *pmd, dm_block_t *result);
 
-int dm_pool_block_is_used(struct dm_pool_metadata *pmd, dm_block_t b, bool *result);
+int dm_pool_block_is_shared(struct dm_pool_metadata *pmd, dm_block_t b, bool *result);
 
 int dm_pool_inc_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e);
 int dm_pool_dec_data_range(struct dm_pool_metadata *pmd, dm_block_t b, dm_block_t e);
index dadd969..e83b636 100644 (file)
@@ -257,6 +257,7 @@ struct pool {
 
        spinlock_t lock;
        struct bio_list deferred_flush_bios;
+       struct bio_list deferred_flush_completions;
        struct list_head prepared_mappings;
        struct list_head prepared_discards;
        struct list_head prepared_discards_pt2;
@@ -956,6 +957,39 @@ static void process_prepared_mapping_fail(struct dm_thin_new_mapping *m)
        mempool_free(m, &m->tc->pool->mapping_pool);
 }
 
+static void complete_overwrite_bio(struct thin_c *tc, struct bio *bio)
+{
+       struct pool *pool = tc->pool;
+       unsigned long flags;
+
+       /*
+        * If the bio has the REQ_FUA flag set we must commit the metadata
+        * before signaling its completion.
+        */
+       if (!bio_triggers_commit(tc, bio)) {
+               bio_endio(bio);
+               return;
+       }
+
+       /*
+        * Complete bio with an error if earlier I/O caused changes to the
+        * metadata that can't be committed, e.g, due to I/O errors on the
+        * metadata device.
+        */
+       if (dm_thin_aborted_changes(tc->td)) {
+               bio_io_error(bio);
+               return;
+       }
+
+       /*
+        * Batch together any bios that trigger commits and then issue a
+        * single commit for them in process_deferred_bios().
+        */
+       spin_lock_irqsave(&pool->lock, flags);
+       bio_list_add(&pool->deferred_flush_completions, bio);
+       spin_unlock_irqrestore(&pool->lock, flags);
+}
+
 static void process_prepared_mapping(struct dm_thin_new_mapping *m)
 {
        struct thin_c *tc = m->tc;
@@ -988,7 +1022,7 @@ static void process_prepared_mapping(struct dm_thin_new_mapping *m)
         */
        if (bio) {
                inc_remap_and_issue_cell(tc, m->cell, m->data_block);
-               bio_endio(bio);
+               complete_overwrite_bio(tc, bio);
        } else {
                inc_all_io_entry(tc->pool, m->cell->holder);
                remap_and_issue(tc, m->cell->holder, m->data_block);
@@ -1048,7 +1082,7 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m
         * passdown we have to check that these blocks are now unused.
         */
        int r = 0;
-       bool used = true;
+       bool shared = true;
        struct thin_c *tc = m->tc;
        struct pool *pool = tc->pool;
        dm_block_t b = m->data_block, e, end = m->data_block + m->virt_end - m->virt_begin;
@@ -1058,11 +1092,11 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m
        while (b != end) {
                /* find start of unmapped run */
                for (; b < end; b++) {
-                       r = dm_pool_block_is_used(pool->pmd, b, &used);
+                       r = dm_pool_block_is_shared(pool->pmd, b, &shared);
                        if (r)
                                goto out;
 
-                       if (!used)
+                       if (!shared)
                                break;
                }
 
@@ -1071,11 +1105,11 @@ static void passdown_double_checking_shared_status(struct dm_thin_new_mapping *m
 
                /* find end of run */
                for (e = b + 1; e != end; e++) {
-                       r = dm_pool_block_is_used(pool->pmd, e, &used);
+                       r = dm_pool_block_is_shared(pool->pmd, e, &shared);
                        if (r)
                                goto out;
 
-                       if (used)
+                       if (shared)
                                break;
                }
 
@@ -2317,7 +2351,7 @@ static void process_deferred_bios(struct pool *pool)
 {
        unsigned long flags;
        struct bio *bio;
-       struct bio_list bios;
+       struct bio_list bios, bio_completions;
        struct thin_c *tc;
 
        tc = get_first_thin(pool);
@@ -2328,26 +2362,36 @@ static void process_deferred_bios(struct pool *pool)
        }
 
        /*
-        * If there are any deferred flush bios, we must commit
-        * the metadata before issuing them.
+        * If there are any deferred flush bios, we must commit the metadata
+        * before issuing them or signaling their completion.
         */
        bio_list_init(&bios);
+       bio_list_init(&bio_completions);
+
        spin_lock_irqsave(&pool->lock, flags);
        bio_list_merge(&bios, &pool->deferred_flush_bios);
        bio_list_init(&pool->deferred_flush_bios);
+
+       bio_list_merge(&bio_completions, &pool->deferred_flush_completions);
+       bio_list_init(&pool->deferred_flush_completions);
        spin_unlock_irqrestore(&pool->lock, flags);
 
-       if (bio_list_empty(&bios) &&
+       if (bio_list_empty(&bios) && bio_list_empty(&bio_completions) &&
            !(dm_pool_changed_this_transaction(pool->pmd) && need_commit_due_to_time(pool)))
                return;
 
        if (commit(pool)) {
+               bio_list_merge(&bios, &bio_completions);
+
                while ((bio = bio_list_pop(&bios)))
                        bio_io_error(bio);
                return;
        }
        pool->last_commit_jiffies = jiffies;
 
+       while ((bio = bio_list_pop(&bio_completions)))
+               bio_endio(bio);
+
        while ((bio = bio_list_pop(&bios)))
                generic_make_request(bio);
 }
@@ -2954,6 +2998,7 @@ static struct pool *pool_create(struct mapped_device *pool_md,
        INIT_DELAYED_WORK(&pool->no_space_timeout, do_no_space_timeout);
        spin_lock_init(&pool->lock);
        bio_list_init(&pool->deferred_flush_bios);
+       bio_list_init(&pool->deferred_flush_completions);
        INIT_LIST_HEAD(&pool->prepared_mappings);
        INIT_LIST_HEAD(&pool->prepared_discards);
        INIT_LIST_HEAD(&pool->prepared_discards_pt2);
index d67c95e..515e6af 100644 (file)
@@ -699,7 +699,7 @@ static void end_io_acct(struct dm_io *io)
                                    true, duration, &io->stats_aux);
 
        /* nudge anyone waiting on suspend queue */
-       if (unlikely(waitqueue_active(&md->wait)))
+       if (unlikely(wq_has_sleeper(&md->wait)))
                wake_up(&md->wait);
 }
 
@@ -1320,7 +1320,7 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio,
 
        __bio_clone_fast(clone, bio);
 
-       if (unlikely(bio_integrity(bio) != NULL)) {
+       if (bio_integrity(bio)) {
                int r;
 
                if (unlikely(!dm_target_has_integrity(tio->ti->type) &&
@@ -1339,7 +1339,7 @@ static int clone_bio(struct dm_target_io *tio, struct bio *bio,
        bio_advance(clone, to_bytes(sector - clone->bi_iter.bi_sector));
        clone->bi_iter.bi_size = to_bytes(len);
 
-       if (unlikely(bio_integrity(bio) != NULL))
+       if (bio_integrity(bio))
                bio_integrity_trim(clone);
 
        return 0;
@@ -1588,6 +1588,9 @@ static void init_clone_info(struct clone_info *ci, struct mapped_device *md,
        ci->sector = bio->bi_iter.bi_sector;
 }
 
+#define __dm_part_stat_sub(part, field, subnd) \
+       (part_stat_get(part, field) -= (subnd))
+
 /*
  * Entry point to split a bio into clones and submit them to the targets.
  */
@@ -1642,7 +1645,21 @@ static blk_qc_t __split_and_process_bio(struct mapped_device *md,
                                struct bio *b = bio_split(bio, bio_sectors(bio) - ci.sector_count,
                                                          GFP_NOIO, &md->queue->bio_split);
                                ci.io->orig_bio = b;
+
+                               /*
+                                * Adjust IO stats for each split, otherwise upon queue
+                                * reentry there will be redundant IO accounting.
+                                * NOTE: this is a stop-gap fix, a proper fix involves
+                                * significant refactoring of DM core's bio splitting
+                                * (by eliminating DM's splitting and just using bio_split)
+                                */
+                               part_stat_lock();
+                               __dm_part_stat_sub(&dm_disk(md)->part0,
+                                                  sectors[op_stat_group(bio_op(bio))], ci.sector_count);
+                               part_stat_unlock();
+
                                bio_chain(b, bio);
+                               trace_block_split(md->queue, b, bio->bi_iter.bi_sector);
                                ret = generic_make_request(bio);
                                break;
                        }
@@ -1713,6 +1730,15 @@ out:
        return ret;
 }
 
+static blk_qc_t dm_process_bio(struct mapped_device *md,
+                              struct dm_table *map, struct bio *bio)
+{
+       if (dm_get_md_type(md) == DM_TYPE_NVME_BIO_BASED)
+               return __process_bio(md, map, bio);
+       else
+               return __split_and_process_bio(md, map, bio);
+}
+
 static blk_qc_t dm_make_request(struct request_queue *q, struct bio *bio)
 {
        struct mapped_device *md = q->queuedata;
@@ -1733,10 +1759,7 @@ static blk_qc_t dm_make_request(struct request_queue *q, struct bio *bio)
                return ret;
        }
 
-       if (dm_get_md_type(md) == DM_TYPE_NVME_BIO_BASED)
-               ret = __process_bio(md, map, bio);
-       else
-               ret = __split_and_process_bio(md, map, bio);
+       ret = dm_process_bio(md, map, bio);
 
        dm_put_live_table(md, srcu_idx);
        return ret;
@@ -2415,9 +2438,9 @@ static void dm_wq_work(struct work_struct *work)
                        break;
 
                if (dm_request_based(md))
-                       generic_make_request(c);
+                       (void) generic_make_request(c);
                else
-                       __split_and_process_bio(md, map, c);
+                       (void) dm_process_bio(md, map, c);
        }
 
        dm_put_live_table(md, srcu_idx);
index fd4af4d..05ffffb 100644 (file)
@@ -207,15 +207,10 @@ static bool create_on_open = true;
 struct bio *bio_alloc_mddev(gfp_t gfp_mask, int nr_iovecs,
                            struct mddev *mddev)
 {
-       struct bio *b;
-
        if (!mddev || !bioset_initialized(&mddev->bio_set))
                return bio_alloc(gfp_mask, nr_iovecs);
 
-       b = bio_alloc_bioset(gfp_mask, nr_iovecs, &mddev->bio_set);
-       if (!b)
-               return NULL;
-       return b;
+       return bio_alloc_bioset(gfp_mask, nr_iovecs, &mddev->bio_set);
 }
 EXPORT_SYMBOL_GPL(bio_alloc_mddev);
 
index 1d54109..fa47249 100644 (file)
@@ -1863,6 +1863,20 @@ static void end_sync_read(struct bio *bio)
                reschedule_retry(r1_bio);
 }
 
+static void abort_sync_write(struct mddev *mddev, struct r1bio *r1_bio)
+{
+       sector_t sync_blocks = 0;
+       sector_t s = r1_bio->sector;
+       long sectors_to_go = r1_bio->sectors;
+
+       /* make sure these bits don't get cleared. */
+       do {
+               md_bitmap_end_sync(mddev->bitmap, s, &sync_blocks, 1);
+               s += sync_blocks;
+               sectors_to_go -= sync_blocks;
+       } while (sectors_to_go > 0);
+}
+
 static void end_sync_write(struct bio *bio)
 {
        int uptodate = !bio->bi_status;
@@ -1874,15 +1888,7 @@ static void end_sync_write(struct bio *bio)
        struct md_rdev *rdev = conf->mirrors[find_bio_disk(r1_bio, bio)].rdev;
 
        if (!uptodate) {
-               sector_t sync_blocks = 0;
-               sector_t s = r1_bio->sector;
-               long sectors_to_go = r1_bio->sectors;
-               /* make sure these bits doesn't get cleared. */
-               do {
-                       md_bitmap_end_sync(mddev->bitmap, s, &sync_blocks, 1);
-                       s += sync_blocks;
-                       sectors_to_go -= sync_blocks;
-               } while (sectors_to_go > 0);
+               abort_sync_write(mddev, r1_bio);
                set_bit(WriteErrorSeen, &rdev->flags);
                if (!test_and_set_bit(WantReplacement, &rdev->flags))
                        set_bit(MD_RECOVERY_NEEDED, &
@@ -2172,8 +2178,10 @@ static void sync_request_write(struct mddev *mddev, struct r1bio *r1_bio)
                     (i == r1_bio->read_disk ||
                      !test_bit(MD_RECOVERY_SYNC, &mddev->recovery))))
                        continue;
-               if (test_bit(Faulty, &conf->mirrors[i].rdev->flags))
+               if (test_bit(Faulty, &conf->mirrors[i].rdev->flags)) {
+                       abort_sync_write(mddev, r1_bio);
                        continue;
+               }
 
                bio_set_op_attrs(wbio, REQ_OP_WRITE, 0);
                if (test_bit(FailFast, &conf->mirrors[i].rdev->flags))
index ec3a5ef..cbbe6b6 100644 (file)
@@ -1935,12 +1935,14 @@ out:
 }
 
 static struct stripe_head *
-r5c_recovery_alloc_stripe(struct r5conf *conf,
-                         sector_t stripe_sect)
+r5c_recovery_alloc_stripe(
+               struct r5conf *conf,
+               sector_t stripe_sect,
+               int noblock)
 {
        struct stripe_head *sh;
 
-       sh = raid5_get_active_stripe(conf, stripe_sect, 0, 1, 0);
+       sh = raid5_get_active_stripe(conf, stripe_sect, 0, noblock, 0);
        if (!sh)
                return NULL;  /* no more stripe available */
 
@@ -2150,7 +2152,7 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
                                                stripe_sect);
 
                if (!sh) {
-                       sh = r5c_recovery_alloc_stripe(conf, stripe_sect);
+                       sh = r5c_recovery_alloc_stripe(conf, stripe_sect, 1);
                        /*
                         * cannot get stripe from raid5_get_active_stripe
                         * try replay some stripes
@@ -2159,20 +2161,29 @@ r5c_recovery_analyze_meta_block(struct r5l_log *log,
                                r5c_recovery_replay_stripes(
                                        cached_stripe_list, ctx);
                                sh = r5c_recovery_alloc_stripe(
-                                       conf, stripe_sect);
+                                       conf, stripe_sect, 1);
                        }
                        if (!sh) {
+                               int new_size = conf->min_nr_stripes * 2;
                                pr_debug("md/raid:%s: Increasing stripe cache size to %d to recovery data on journal.\n",
                                        mdname(mddev),
-                                       conf->min_nr_stripes * 2);
-                               raid5_set_cache_size(mddev,
-                                                    conf->min_nr_stripes * 2);
-                               sh = r5c_recovery_alloc_stripe(conf,
-                                                              stripe_sect);
+                                       new_size);
+                               ret = raid5_set_cache_size(mddev, new_size);
+                               if (conf->min_nr_stripes <= new_size / 2) {
+                                       pr_err("md/raid:%s: Cannot increase cache size, ret=%d, new_size=%d, min_nr_stripes=%d, max_nr_stripes=%d\n",
+                                               mdname(mddev),
+                                               ret,
+                                               new_size,
+                                               conf->min_nr_stripes,
+                                               conf->max_nr_stripes);
+                                       return -ENOMEM;
+                               }
+                               sh = r5c_recovery_alloc_stripe(
+                                       conf, stripe_sect, 0);
                        }
                        if (!sh) {
                                pr_err("md/raid:%s: Cannot get enough stripes due to memory pressure. Recovery failed.\n",
-                                      mdname(mddev));
+                                       mdname(mddev));
                                return -ENOMEM;
                        }
                        list_add_tail(&sh->lru, cached_stripe_list);
index 4990f03..cecea90 100644 (file)
@@ -6369,6 +6369,7 @@ raid5_show_stripe_cache_size(struct mddev *mddev, char *page)
 int
 raid5_set_cache_size(struct mddev *mddev, int size)
 {
+       int result = 0;
        struct r5conf *conf = mddev->private;
 
        if (size <= 16 || size > 32768)
@@ -6385,11 +6386,14 @@ raid5_set_cache_size(struct mddev *mddev, int size)
 
        mutex_lock(&conf->cache_size_mutex);
        while (size > conf->max_nr_stripes)
-               if (!grow_one_stripe(conf, GFP_KERNEL))
+               if (!grow_one_stripe(conf, GFP_KERNEL)) {
+                       conf->min_nr_stripes = conf->max_nr_stripes;
+                       result = -ENOMEM;
                        break;
+               }
        mutex_unlock(&conf->cache_size_mutex);
 
-       return 0;
+       return result;
 }
 EXPORT_SYMBOL(raid5_set_cache_size);
 
index 447baae..cdb79ae 100644 (file)
@@ -218,8 +218,8 @@ static int cio2_fbpt_init(struct cio2_device *cio2, struct cio2_queue *q)
 {
        struct device *dev = &cio2->pci_dev->dev;
 
-       q->fbpt = dma_zalloc_coherent(dev, CIO2_FBPT_SIZE, &q->fbpt_bus_addr,
-                                     GFP_KERNEL);
+       q->fbpt = dma_alloc_coherent(dev, CIO2_FBPT_SIZE, &q->fbpt_bus_addr,
+                                    GFP_KERNEL);
        if (!q->fbpt)
                return -ENOMEM;
 
index e80123c..060c0ad 100644 (file)
@@ -49,7 +49,7 @@ int mtk_vcodec_mem_alloc(struct mtk_vcodec_ctx *data,
        struct mtk_vcodec_ctx *ctx = (struct mtk_vcodec_ctx *)data;
        struct device *dev = &ctx->dev->plat_dev->dev;
 
-       mem->va = dma_zalloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL);
+       mem->va = dma_alloc_coherent(dev, size, &mem->dma_addr, GFP_KERNEL);
        if (!mem->va) {
                mtk_v4l2_err("%s dma_alloc size=%ld failed!", dev_name(dev),
                             size);
index d01821a..89d9c4c 100644 (file)
@@ -807,7 +807,9 @@ static void vim2m_stop_streaming(struct vb2_queue *q)
        struct vb2_v4l2_buffer *vbuf;
        unsigned long flags;
 
-       cancel_delayed_work_sync(&dev->work_run);
+       if (v4l2_m2m_get_curr_priv(dev->m2m_dev) == ctx)
+               cancel_delayed_work_sync(&dev->work_run);
+
        for (;;) {
                if (V4L2_TYPE_IS_OUTPUT(q->type))
                        vbuf = v4l2_m2m_src_buf_remove(ctx->fh.m2m_ctx);
index 1441a73..90aad46 100644 (file)
@@ -287,6 +287,7 @@ static void v4l_print_format(const void *arg, bool write_only)
        const struct v4l2_window *win;
        const struct v4l2_sdr_format *sdr;
        const struct v4l2_meta_format *meta;
+       u32 planes;
        unsigned i;
 
        pr_cont("type=%s", prt_names(p->type, v4l2_type_names));
@@ -317,7 +318,8 @@ static void v4l_print_format(const void *arg, bool write_only)
                        prt_names(mp->field, v4l2_field_names),
                        mp->colorspace, mp->num_planes, mp->flags,
                        mp->ycbcr_enc, mp->quantization, mp->xfer_func);
-               for (i = 0; i < mp->num_planes; i++)
+               planes = min_t(u32, mp->num_planes, VIDEO_MAX_PLANES);
+               for (i = 0; i < planes; i++)
                        printk(KERN_DEBUG "plane %u: bytesperline=%u sizeimage=%u\n", i,
                                        mp->plane_fmt[i].bytesperline,
                                        mp->plane_fmt[i].sizeimage);
@@ -1551,8 +1553,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_s_fmt_vid_cap_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+               if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+                       break;
                for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
-                       CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+                       CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+                                         bytesperline);
                return ops->vidioc_s_fmt_vid_cap_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
                if (unlikely(!ops->vidioc_s_fmt_vid_overlay))
@@ -1581,8 +1586,11 @@ static int v4l_s_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_s_fmt_vid_out_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+               if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+                       break;
                for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
-                       CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+                       CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+                                         bytesperline);
                return ops->vidioc_s_fmt_vid_out_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
                if (unlikely(!ops->vidioc_s_fmt_vid_out_overlay))
@@ -1648,8 +1656,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_try_fmt_vid_cap_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+               if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+                       break;
                for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
-                       CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+                       CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+                                         bytesperline);
                return ops->vidioc_try_fmt_vid_cap_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OVERLAY:
                if (unlikely(!ops->vidioc_try_fmt_vid_overlay))
@@ -1678,8 +1689,11 @@ static int v4l_try_fmt(const struct v4l2_ioctl_ops *ops,
                if (unlikely(!ops->vidioc_try_fmt_vid_out_mplane))
                        break;
                CLEAR_AFTER_FIELD(p, fmt.pix_mp.xfer_func);
+               if (p->fmt.pix_mp.num_planes > VIDEO_MAX_PLANES)
+                       break;
                for (i = 0; i < p->fmt.pix_mp.num_planes; i++)
-                       CLEAR_AFTER_FIELD(p, fmt.pix_mp.plane_fmt[i].bytesperline);
+                       CLEAR_AFTER_FIELD(&p->fmt.pix_mp.plane_fmt[i],
+                                         bytesperline);
                return ops->vidioc_try_fmt_vid_out_mplane(file, fh, arg);
        case V4L2_BUF_TYPE_VIDEO_OUTPUT_OVERLAY:
                if (unlikely(!ops->vidioc_try_fmt_vid_out_overlay))
index 8c5dfdc..76f9909 100644 (file)
@@ -102,6 +102,7 @@ config MFD_AAT2870_CORE
 config MFD_AT91_USART
        tristate "AT91 USART Driver"
        select MFD_CORE
+       depends on ARCH_AT91 || COMPILE_TEST
        help
          Select this to get support for AT91 USART IP. This is a wrapper
          over at91-usart-serial driver and usart-spi-driver. Only one function
@@ -1418,7 +1419,7 @@ config MFD_TPS65217
 
 config MFD_TPS68470
        bool "TI TPS68470 Power Management / LED chips"
-       depends on ACPI && I2C=y
+       depends on ACPI && PCI && I2C=y
        select MFD_CORE
        select REGMAP_I2C
        select I2C_DESIGNWARE_PLATFORM
index 30d09d1..11ab17f 100644 (file)
@@ -261,7 +261,7 @@ static int get_register_interruptible(struct ab8500 *ab8500, u8 bank,
        mutex_unlock(&ab8500->lock);
        dev_vdbg(ab8500->dev, "rd: addr %#x => data %#x\n", addr, ret);
 
-       return ret;
+       return (ret < 0) ? ret : 0;
 }
 
 static int ab8500_get_register(struct device *dev, u8 bank,
index e1450a5..3c97f2c 100644 (file)
@@ -641,9 +641,9 @@ static const struct mfd_cell axp221_cells[] = {
 
 static const struct mfd_cell axp223_cells[] = {
        {
-               .name                   = "axp221-pek",
-               .num_resources          = ARRAY_SIZE(axp22x_pek_resources),
-               .resources              = axp22x_pek_resources,
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp22x_pek_resources),
+               .resources      = axp22x_pek_resources,
        }, {
                .name           = "axp22x-adc",
                .of_compatible  = "x-powers,axp221-adc",
@@ -651,7 +651,7 @@ static const struct mfd_cell axp223_cells[] = {
                .name           = "axp20x-battery-power-supply",
                .of_compatible  = "x-powers,axp221-battery-power-supply",
        }, {
-               .name                   = "axp20x-regulator",
+               .name           = "axp20x-regulator",
        }, {
                .name           = "axp20x-ac-power-supply",
                .of_compatible  = "x-powers,axp221-ac-power-supply",
@@ -667,9 +667,9 @@ static const struct mfd_cell axp223_cells[] = {
 
 static const struct mfd_cell axp152_cells[] = {
        {
-               .name                   = "axp20x-pek",
-               .num_resources          = ARRAY_SIZE(axp152_pek_resources),
-               .resources              = axp152_pek_resources,
+               .name           = "axp20x-pek",
+               .num_resources  = ARRAY_SIZE(axp152_pek_resources),
+               .resources      = axp152_pek_resources,
        },
 };
 
@@ -698,87 +698,101 @@ static const struct resource axp288_charger_resources[] = {
 
 static const struct mfd_cell axp288_cells[] = {
        {
-               .name = "axp288_adc",
-               .num_resources = ARRAY_SIZE(axp288_adc_resources),
-               .resources = axp288_adc_resources,
-       },
-       {
-               .name = "axp288_extcon",
-               .num_resources = ARRAY_SIZE(axp288_extcon_resources),
-               .resources = axp288_extcon_resources,
-       },
-       {
-               .name = "axp288_charger",
-               .num_resources = ARRAY_SIZE(axp288_charger_resources),
-               .resources = axp288_charger_resources,
-       },
-       {
-               .name = "axp288_fuel_gauge",
-               .num_resources = ARRAY_SIZE(axp288_fuel_gauge_resources),
-               .resources = axp288_fuel_gauge_resources,
-       },
-       {
-               .name = "axp221-pek",
-               .num_resources = ARRAY_SIZE(axp288_power_button_resources),
-               .resources = axp288_power_button_resources,
-       },
-       {
-               .name = "axp288_pmic_acpi",
+               .name           = "axp288_adc",
+               .num_resources  = ARRAY_SIZE(axp288_adc_resources),
+               .resources      = axp288_adc_resources,
+       }, {
+               .name           = "axp288_extcon",
+               .num_resources  = ARRAY_SIZE(axp288_extcon_resources),
+               .resources      = axp288_extcon_resources,
+       }, {
+               .name           = "axp288_charger",
+               .num_resources  = ARRAY_SIZE(axp288_charger_resources),
+               .resources      = axp288_charger_resources,
+       }, {
+               .name           = "axp288_fuel_gauge",
+               .num_resources  = ARRAY_SIZE(axp288_fuel_gauge_resources),
+               .resources      = axp288_fuel_gauge_resources,
+       }, {
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp288_power_button_resources),
+               .resources      = axp288_power_button_resources,
+       }, {
+               .name           = "axp288_pmic_acpi",
        },
 };
 
 static const struct mfd_cell axp803_cells[] = {
        {
-               .name                   = "axp221-pek",
-               .num_resources          = ARRAY_SIZE(axp803_pek_resources),
-               .resources              = axp803_pek_resources,
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp803_pek_resources),
+               .resources      = axp803_pek_resources,
+       }, {
+               .name           = "axp20x-gpio",
+               .of_compatible  = "x-powers,axp813-gpio",
+       }, {
+               .name           = "axp813-adc",
+               .of_compatible  = "x-powers,axp813-adc",
+       }, {
+               .name           = "axp20x-battery-power-supply",
+               .of_compatible  = "x-powers,axp813-battery-power-supply",
+       }, {
+               .name           = "axp20x-ac-power-supply",
+               .of_compatible  = "x-powers,axp813-ac-power-supply",
+               .num_resources  = ARRAY_SIZE(axp20x_ac_power_supply_resources),
+               .resources      = axp20x_ac_power_supply_resources,
        },
-       {       .name                   = "axp20x-regulator" },
+       {       .name           = "axp20x-regulator" },
 };
 
 static const struct mfd_cell axp806_self_working_cells[] = {
        {
-               .name                   = "axp221-pek",
-               .num_resources          = ARRAY_SIZE(axp806_pek_resources),
-               .resources              = axp806_pek_resources,
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp806_pek_resources),
+               .resources      = axp806_pek_resources,
        },
-       {       .name                   = "axp20x-regulator" },
+       {       .name           = "axp20x-regulator" },
 };
 
 static const struct mfd_cell axp806_cells[] = {
        {
-               .id                     = 2,
-               .name                   = "axp20x-regulator",
+               .id             = 2,
+               .name           = "axp20x-regulator",
        },
 };
 
 static const struct mfd_cell axp809_cells[] = {
        {
-               .name                   = "axp221-pek",
-               .num_resources          = ARRAY_SIZE(axp809_pek_resources),
-               .resources              = axp809_pek_resources,
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp809_pek_resources),
+               .resources      = axp809_pek_resources,
        }, {
-               .id                     = 1,
-               .name                   = "axp20x-regulator",
+               .id             = 1,
+               .name           = "axp20x-regulator",
        },
 };
 
 static const struct mfd_cell axp813_cells[] = {
        {
-               .name                   = "axp221-pek",
-               .num_resources          = ARRAY_SIZE(axp803_pek_resources),
-               .resources              = axp803_pek_resources,
+               .name           = "axp221-pek",
+               .num_resources  = ARRAY_SIZE(axp803_pek_resources),
+               .resources      = axp803_pek_resources,
        }, {
-               .name                   = "axp20x-regulator",
+               .name           = "axp20x-regulator",
        }, {
-               .name                   = "axp20x-gpio",
-               .of_compatible          = "x-powers,axp813-gpio",
+               .name           = "axp20x-gpio",
+               .of_compatible  = "x-powers,axp813-gpio",
        }, {
-               .name                   = "axp813-adc",
-               .of_compatible          = "x-powers,axp813-adc",
+               .name           = "axp813-adc",
+               .of_compatible  = "x-powers,axp813-adc",
        }, {
                .name           = "axp20x-battery-power-supply",
                .of_compatible  = "x-powers,axp813-battery-power-supply",
+       }, {
+               .name           = "axp20x-ac-power-supply",
+               .of_compatible  = "x-powers,axp813-ac-power-supply",
+               .num_resources  = ARRAY_SIZE(axp20x_ac_power_supply_resources),
+               .resources      = axp20x_ac_power_supply_resources,
        },
 };
 
index 503979c..fab3cdc 100644 (file)
@@ -59,6 +59,7 @@ static const struct regmap_access_table bd9571mwv_writable_table = {
 };
 
 static const struct regmap_range bd9571mwv_volatile_yes_ranges[] = {
+       regmap_reg_range(BD9571MWV_DVFS_MONIVDAC, BD9571MWV_DVFS_MONIVDAC),
        regmap_reg_range(BD9571MWV_GPIO_IN, BD9571MWV_GPIO_IN),
        regmap_reg_range(BD9571MWV_GPIO_INT, BD9571MWV_GPIO_INT),
        regmap_reg_range(BD9571MWV_INT_INTREQ, BD9571MWV_INT_INTREQ),
index b99a194..2d0fee4 100644 (file)
@@ -499,6 +499,7 @@ static int ec_device_remove(struct platform_device *pdev)
 
        cros_ec_debugfs_remove(ec);
 
+       mfd_remove_devices(ec->dev);
        cdev_del(&ec->cdev);
        device_unregister(&ec->class_dev);
        return 0;
index 5970b8d..aec20e1 100644 (file)
@@ -2584,7 +2584,7 @@ static struct irq_chip prcmu_irq_chip = {
        .irq_unmask     = prcmu_irq_unmask,
 };
 
-static __init char *fw_project_name(u32 project)
+static char *fw_project_name(u32 project)
 {
        switch (project) {
        case PRCMU_FW_PROJECT_U8500:
@@ -2732,7 +2732,7 @@ void __init db8500_prcmu_early_init(u32 phy_base, u32 size)
        INIT_WORK(&mb0_transfer.mask_work, prcmu_mask_work);
 }
 
-static void __init init_prcm_registers(void)
+static void init_prcm_registers(void)
 {
        u32 val;
 
index ca829f8..2713de9 100644 (file)
@@ -82,11 +82,13 @@ static void exynos_lpass_enable(struct exynos_lpass *lpass)
                     LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S);
 
        regmap_write(lpass->top, SFR_LPASS_INTR_CPU_MASK,
-                    LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S);
+                    LPASS_INTR_SFR | LPASS_INTR_DMA | LPASS_INTR_I2S |
+                    LPASS_INTR_UART);
 
        exynos_lpass_core_sw_reset(lpass, LPASS_I2S_SW_RESET);
        exynos_lpass_core_sw_reset(lpass, LPASS_DMA_SW_RESET);
        exynos_lpass_core_sw_reset(lpass, LPASS_MEM_SW_RESET);
+       exynos_lpass_core_sw_reset(lpass, LPASS_UART_SW_RESET);
 }
 
 static void exynos_lpass_disable(struct exynos_lpass *lpass)
index 440030c..2a77988 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/gpio.h>
 #include <linux/mfd/core.h>
 #include <linux/module.h>
+#include <linux/mutex.h>
 #include <linux/notifier.h>
 #include <linux/of.h>
 #include <linux/of_gpio.h>
@@ -155,7 +156,7 @@ static int madera_wait_for_boot(struct madera *madera)
                usleep_range(MADERA_BOOT_POLL_INTERVAL_USEC / 2,
                             MADERA_BOOT_POLL_INTERVAL_USEC);
                regmap_read(madera->regmap, MADERA_IRQ1_RAW_STATUS_1, &val);
-       };
+       }
 
        if (!(val & MADERA_BOOT_DONE_STS1)) {
                dev_err(madera->dev, "Polling BOOT_DONE_STS timed out\n");
@@ -357,6 +358,8 @@ int madera_dev_init(struct madera *madera)
 
        dev_set_drvdata(madera->dev, madera);
        BLOCKING_INIT_NOTIFIER_HEAD(&madera->notifier);
+       mutex_init(&madera->dapm_ptr_lock);
+
        madera_set_micbias_info(madera);
 
        /*
index d821736..d8ddd1a 100644 (file)
@@ -280,7 +280,7 @@ static int max77620_config_fps(struct max77620_chip *chip,
 
        for (fps_id = 0; fps_id < MAX77620_FPS_COUNT; fps_id++) {
                sprintf(fps_name, "fps%d", fps_id);
-               if (!strcmp(fps_np->name, fps_name))
+               if (of_node_name_eq(fps_np, fps_name))
                        break;
        }
 
index f475e84..d0bf50e 100644 (file)
@@ -274,7 +274,9 @@ int mc13xxx_adc_do_conversion(struct mc13xxx *mc13xxx, unsigned int mode,
 
        mc13xxx->adcflags |= MC13XXX_ADC_WORKING;
 
-       mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0);
+       ret = mc13xxx_reg_read(mc13xxx, MC13XXX_ADC0, &old_adc0);
+       if (ret)
+               goto out;
 
        adc0 = MC13XXX_ADC0_ADINC1 | MC13XXX_ADC0_ADINC2 |
               MC13XXX_ADC0_CHRGRAWDIV;
index 77b64bd..ab24e17 100644 (file)
@@ -329,8 +329,7 @@ static int mt6397_probe(struct platform_device *pdev)
 
        default:
                dev_err(&pdev->dev, "unsupported chip: %d\n", id);
-               ret = -ENODEV;
-               break;
+               return -ENODEV;
        }
 
        if (ret) {
index 52fafea..8d420c3 100644 (file)
@@ -638,6 +638,10 @@ static int qcom_rpm_probe(struct platform_device *pdev)
                return -EFAULT;
        }
 
+       writel(fw_version[0], RPM_CTRL_REG(rpm, 0));
+       writel(fw_version[1], RPM_CTRL_REG(rpm, 1));
+       writel(fw_version[2], RPM_CTRL_REG(rpm, 2));
+
        dev_info(&pdev->dev, "RPM firmware %u.%u.%u\n", fw_version[0],
                                                        fw_version[1],
                                                        fw_version[2]);
index 2a83696..26c7b63 100644 (file)
@@ -109,7 +109,7 @@ struct rave_sp_reply {
 /**
  * struct rave_sp_checksum - Variant specific checksum implementation details
  *
- * @length:    Caculated checksum length
+ * @length:    Calculated checksum length
  * @subroutine:        Utilized checksum algorithm implementation
  */
 struct rave_sp_checksum {
index 566caca..7569a4b 100644 (file)
@@ -1302,17 +1302,17 @@ static void stmpe_of_probe(struct stmpe_platform_data *pdata,
        pdata->autosleep = (pdata->autosleep_timeout) ? true : false;
 
        for_each_child_of_node(np, child) {
-               if (!strcmp(child->name, "stmpe_gpio")) {
+               if (of_node_name_eq(child, "stmpe_gpio")) {
                        pdata->blocks |= STMPE_BLOCK_GPIO;
-               } else if (!strcmp(child->name, "stmpe_keypad")) {
+               } else if (of_node_name_eq(child, "stmpe_keypad")) {
                        pdata->blocks |= STMPE_BLOCK_KEYPAD;
-               } else if (!strcmp(child->name, "stmpe_touchscreen")) {
+               } else if (of_node_name_eq(child, "stmpe_touchscreen")) {
                        pdata->blocks |= STMPE_BLOCK_TOUCHSCREEN;
-               } else if (!strcmp(child->name, "stmpe_adc")) {
+               } else if (of_node_name_eq(child, "stmpe_adc")) {
                        pdata->blocks |= STMPE_BLOCK_ADC;
-               } else if (!strcmp(child->name, "stmpe_pwm")) {
+               } else if (of_node_name_eq(child, "stmpe_pwm")) {
                        pdata->blocks |= STMPE_BLOCK_PWM;
-               } else if (!strcmp(child->name, "stmpe_rotator")) {
+               } else if (of_node_name_eq(child, "stmpe_rotator")) {
                        pdata->blocks |= STMPE_BLOCK_ROTATOR;
                }
        }
index c2d47d7..fd11129 100644 (file)
@@ -264,8 +264,9 @@ static      int ti_tscadc_probe(struct platform_device *pdev)
                cell->pdata_size = sizeof(tscadc);
        }
 
-       err = mfd_add_devices(&pdev->dev, pdev->id, tscadc->cells,
-                       tscadc->used_cells, NULL, 0, NULL);
+       err = mfd_add_devices(&pdev->dev, PLATFORM_DEVID_AUTO,
+                             tscadc->cells, tscadc->used_cells, NULL,
+                             0, NULL);
        if (err < 0)
                goto err_disable_clk;
 
index 910f569..8bcdecf 100644 (file)
@@ -235,9 +235,9 @@ static int tps65218_probe(struct i2c_client *client,
 
        mutex_init(&tps->tps_lock);
 
-       ret = regmap_add_irq_chip(tps->regmap, tps->irq,
-                       IRQF_ONESHOT, 0, &tps65218_irq_chip,
-                       &tps->irq_data);
+       ret = devm_regmap_add_irq_chip(&client->dev, tps->regmap, tps->irq,
+                                      IRQF_ONESHOT, 0, &tps65218_irq_chip,
+                                      &tps->irq_data);
        if (ret < 0)
                return ret;
 
@@ -253,26 +253,9 @@ static int tps65218_probe(struct i2c_client *client,
                              ARRAY_SIZE(tps65218_cells), NULL, 0,
                              regmap_irq_get_domain(tps->irq_data));
 
-       if (ret < 0)
-               goto err_irq;
-
-       return 0;
-
-err_irq:
-       regmap_del_irq_chip(tps->irq, tps->irq_data);
-
        return ret;
 }
 
-static int tps65218_remove(struct i2c_client *client)
-{
-       struct tps65218 *tps = i2c_get_clientdata(client);
-
-       regmap_del_irq_chip(tps->irq, tps->irq_data);
-
-       return 0;
-}
-
 static const struct i2c_device_id tps65218_id_table[] = {
        { "tps65218", TPS65218 },
        { },
@@ -285,7 +268,6 @@ static struct i2c_driver tps65218_driver = {
                .of_match_table = of_tps65218_match_table,
        },
        .probe          = tps65218_probe,
-       .remove         = tps65218_remove,
        .id_table       = tps65218_id_table,
 };
 
index b893797..9c7925c 100644 (file)
@@ -592,6 +592,29 @@ static int tps6586x_i2c_remove(struct i2c_client *client)
        return 0;
 }
 
+static int __maybe_unused tps6586x_i2c_suspend(struct device *dev)
+{
+       struct tps6586x *tps6586x = dev_get_drvdata(dev);
+
+       if (tps6586x->client->irq)
+               disable_irq(tps6586x->client->irq);
+
+       return 0;
+}
+
+static int __maybe_unused tps6586x_i2c_resume(struct device *dev)
+{
+       struct tps6586x *tps6586x = dev_get_drvdata(dev);
+
+       if (tps6586x->client->irq)
+               enable_irq(tps6586x->client->irq);
+
+       return 0;
+}
+
+static SIMPLE_DEV_PM_OPS(tps6586x_pm_ops, tps6586x_i2c_suspend,
+                        tps6586x_i2c_resume);
+
 static const struct i2c_device_id tps6586x_id_table[] = {
        { "tps6586x", 0 },
        { },
@@ -602,6 +625,7 @@ static struct i2c_driver tps6586x_driver = {
        .driver = {
                .name   = "tps6586x",
                .of_match_table = of_match_ptr(tps6586x_of_match),
+               .pm     = &tps6586x_pm_ops,
        },
        .probe          = tps6586x_i2c_probe,
        .remove         = tps6586x_i2c_remove,
index 4be3d23..299016b 100644 (file)
@@ -979,7 +979,7 @@ add_children(struct twl4030_platform_data *pdata, unsigned irq_base,
  * letting it generate the right frequencies for USB, MADC, and
  * other purposes.
  */
-static inline int __init protect_pm_master(void)
+static inline int protect_pm_master(void)
 {
        int e = 0;
 
@@ -988,7 +988,7 @@ static inline int __init protect_pm_master(void)
        return e;
 }
 
-static inline int __init unprotect_pm_master(void)
+static inline int unprotect_pm_master(void)
 {
        int e = 0;
 
index 1ee68bd..16c6e2a 100644 (file)
@@ -1618,6 +1618,7 @@ static const struct reg_default wm5110_reg_default[] = {
        { 0x00000ECD, 0x0000 },    /* R3789  - HPLPF4_2 */
        { 0x00000EE0, 0x0000 },    /* R3808  - ASRC_ENABLE */
        { 0x00000EE2, 0x0000 },    /* R3810  - ASRC_RATE1 */
+       { 0x00000EE3, 0x4000 },    /* R3811  - ASRC_RATE2 */
        { 0x00000EF0, 0x0000 },    /* R3824  - ISRC 1 CTRL 1 */
        { 0x00000EF1, 0x0000 },    /* R3825  - ISRC 1 CTRL 2 */
        { 0x00000EF2, 0x0000 },    /* R3826  - ISRC 1 CTRL 3 */
@@ -2869,6 +2870,7 @@ static bool wm5110_readable_register(struct device *dev, unsigned int reg)
        case ARIZONA_ASRC_ENABLE:
        case ARIZONA_ASRC_STATUS:
        case ARIZONA_ASRC_RATE1:
+       case ARIZONA_ASRC_RATE2:
        case ARIZONA_ISRC_1_CTRL_1:
        case ARIZONA_ISRC_1_CTRL_2:
        case ARIZONA_ISRC_1_CTRL_3:
index efe2fb7..25265fd 100644 (file)
@@ -218,8 +218,8 @@ void *__genwqe_alloc_consistent(struct genwqe_dev *cd, size_t size,
        if (get_order(size) >= MAX_ORDER)
                return NULL;
 
-       return dma_zalloc_coherent(&cd->pci_dev->dev, size, dma_handle,
-                                  GFP_KERNEL);
+       return dma_alloc_coherent(&cd->pci_dev->dev, size, dma_handle,
+                                 GFP_KERNEL);
 }
 
 void __genwqe_free_consistent(struct genwqe_dev *cd, size_t size,
index b8aaa68..2ed23c9 100644 (file)
@@ -820,21 +820,24 @@ static int ibmvmc_send_msg(struct crq_server_adapter *adapter,
  *
  * Return:
  *     0 - Success
+ *     Non-zero - Failure
  */
 static int ibmvmc_open(struct inode *inode, struct file *file)
 {
        struct ibmvmc_file_session *session;
-       int rc = 0;
 
        pr_debug("%s: inode = 0x%lx, file = 0x%lx, state = 0x%x\n", __func__,
                 (unsigned long)inode, (unsigned long)file,
                 ibmvmc.state);
 
        session = kzalloc(sizeof(*session), GFP_KERNEL);
+       if (!session)
+               return -ENOMEM;
+
        session->file = file;
        file->private_data = session;
 
-       return rc;
+       return 0;
 }
 
 /**
index 1fc8ea0..ca4c9cc 100644 (file)
@@ -401,8 +401,11 @@ static void mei_io_list_flush_cl(struct list_head *head,
        struct mei_cl_cb *cb, *next;
 
        list_for_each_entry_safe(cb, next, head, list) {
-               if (cl == cb->cl)
+               if (cl == cb->cl) {
                        list_del_init(&cb->list);
+                       if (cb->fop_type == MEI_FOP_READ)
+                               mei_io_cb_free(cb);
+               }
        }
 }
 
index 78c26ce..8f76165 100644 (file)
@@ -1187,9 +1187,15 @@ int mei_hbm_dispatch(struct mei_device *dev, struct mei_msg_hdr *hdr)
                dma_setup_res = (struct hbm_dma_setup_response *)mei_msg;
 
                if (dma_setup_res->status) {
-                       dev_info(dev->dev, "hbm: dma setup response: failure = %d %s\n",
-                                dma_setup_res->status,
-                                mei_hbm_status_str(dma_setup_res->status));
+                       u8 status = dma_setup_res->status;
+
+                       if (status == MEI_HBMS_NOT_ALLOWED) {
+                               dev_dbg(dev->dev, "hbm: dma setup not allowed\n");
+                       } else {
+                               dev_info(dev->dev, "hbm: dma setup response: failure = %d %s\n",
+                                        status,
+                                        mei_hbm_status_str(status));
+                       }
                        dev->hbm_f_dr_supported = 0;
                        mei_dmam_ring_free(dev);
                }
index e4b10b2..bb1ee98 100644 (file)
 #define MEI_DEV_ID_BXT_M      0x1A9A  /* Broxton M */
 #define MEI_DEV_ID_APL_I      0x5A9A  /* Apollo Lake I */
 
+#define MEI_DEV_ID_DNV_IE     0x19E5  /* Denverton IE */
+
 #define MEI_DEV_ID_GLK        0x319A  /* Gemini Lake */
 
 #define MEI_DEV_ID_KBP        0xA2BA  /* Kaby Point */
 #define MEI_DEV_ID_CNP_H      0xA360  /* Cannon Point H */
 #define MEI_DEV_ID_CNP_H_4    0xA364  /* Cannon Point H 4 (iTouch) */
 
+#define MEI_DEV_ID_ICP_LP     0x34E0  /* Ice Lake Point LP */
+
 /*
  * MEI HW Section
  */
index 73ace2d..3ab946a 100644 (file)
@@ -88,11 +88,13 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
        {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_2, MEI_ME_PCH8_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H, MEI_ME_PCH8_SPS_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_SPT_H_2, MEI_ME_PCH8_SPS_CFG)},
-       {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH8_CFG)},
+       {MEI_PCI_DEVICE(MEI_DEV_ID_LBG, MEI_ME_PCH12_CFG)},
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_BXT_M, MEI_ME_PCH8_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_APL_I, MEI_ME_PCH8_CFG)},
 
+       {MEI_PCI_DEVICE(MEI_DEV_ID_DNV_IE, MEI_ME_PCH8_CFG)},
+
        {MEI_PCI_DEVICE(MEI_DEV_ID_GLK, MEI_ME_PCH8_CFG)},
 
        {MEI_PCI_DEVICE(MEI_DEV_ID_KBP, MEI_ME_PCH8_CFG)},
@@ -103,6 +105,8 @@ static const struct pci_device_id mei_me_pci_tbl[] = {
        {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H, MEI_ME_PCH12_CFG)},
        {MEI_PCI_DEVICE(MEI_DEV_ID_CNP_H_4, MEI_ME_PCH8_CFG)},
 
+       {MEI_PCI_DEVICE(MEI_DEV_ID_ICP_LP, MEI_ME_PCH12_CFG)},
+
        /* required last entry */
        {0, }
 };
index 6b212c8..744757f 100644 (file)
@@ -47,7 +47,8 @@
  * @dc: Virtio device control
  * @vpdev: VOP device which is the parent for this virtio device
  * @vr: Buffer for accessing the VRING
- * @used: Buffer for used
+ * @used_virt: Virtual address of used ring
+ * @used: DMA address of used ring
  * @used_size: Size of the used buffer
  * @reset_done: Track whether VOP reset is complete
  * @virtio_cookie: Cookie returned upon requesting a interrupt
@@ -61,6 +62,7 @@ struct _vop_vdev {
        struct mic_device_ctrl __iomem *dc;
        struct vop_device *vpdev;
        void __iomem *vr[VOP_MAX_VRINGS];
+       void *used_virt[VOP_MAX_VRINGS];
        dma_addr_t used[VOP_MAX_VRINGS];
        int used_size[VOP_MAX_VRINGS];
        struct completion reset_done;
@@ -260,12 +262,12 @@ static bool vop_notify(struct virtqueue *vq)
 static void vop_del_vq(struct virtqueue *vq, int n)
 {
        struct _vop_vdev *vdev = to_vopvdev(vq->vdev);
-       struct vring *vr = (struct vring *)(vq + 1);
        struct vop_device *vpdev = vdev->vpdev;
 
        dma_unmap_single(&vpdev->dev, vdev->used[n],
                         vdev->used_size[n], DMA_BIDIRECTIONAL);
-       free_pages((unsigned long)vr->used, get_order(vdev->used_size[n]));
+       free_pages((unsigned long)vdev->used_virt[n],
+                  get_order(vdev->used_size[n]));
        vring_del_virtqueue(vq);
        vpdev->hw_ops->iounmap(vpdev, vdev->vr[n]);
        vdev->vr[n] = NULL;
@@ -283,6 +285,26 @@ static void vop_del_vqs(struct virtio_device *dev)
                vop_del_vq(vq, idx++);
 }
 
+static struct virtqueue *vop_new_virtqueue(unsigned int index,
+                                     unsigned int num,
+                                     struct virtio_device *vdev,
+                                     bool context,
+                                     void *pages,
+                                     bool (*notify)(struct virtqueue *vq),
+                                     void (*callback)(struct virtqueue *vq),
+                                     const char *name,
+                                     void *used)
+{
+       bool weak_barriers = false;
+       struct vring vring;
+
+       vring_init(&vring, num, pages, MIC_VIRTIO_RING_ALIGN);
+       vring.used = used;
+
+       return __vring_new_virtqueue(index, vring, vdev, weak_barriers, context,
+                                    notify, callback, name);
+}
+
 /*
  * This routine will assign vring's allocated in host/io memory. Code in
  * virtio_ring.c however continues to access this io memory as if it were local
@@ -302,7 +324,6 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
        struct _mic_vring_info __iomem *info;
        void *used;
        int vr_size, _vr_size, err, magic;
-       struct vring *vr;
        u8 type = ioread8(&vdev->desc->type);
 
        if (index >= ioread8(&vdev->desc->num_vq))
@@ -322,17 +343,7 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
                return ERR_PTR(-ENOMEM);
        vdev->vr[index] = va;
        memset_io(va, 0x0, _vr_size);
-       vq = vring_new_virtqueue(
-                               index,
-                               le16_to_cpu(config.num), MIC_VIRTIO_RING_ALIGN,
-                               dev,
-                               false,
-                               ctx,
-                               (void __force *)va, vop_notify, callback, name);
-       if (!vq) {
-               err = -ENOMEM;
-               goto unmap;
-       }
+
        info = va + _vr_size;
        magic = ioread32(&info->magic);
 
@@ -341,18 +352,27 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
                goto unmap;
        }
 
-       /* Allocate and reassign used ring now */
        vdev->used_size[index] = PAGE_ALIGN(sizeof(__u16) * 3 +
                                             sizeof(struct vring_used_elem) *
                                             le16_to_cpu(config.num));
        used = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
                                        get_order(vdev->used_size[index]));
+       vdev->used_virt[index] = used;
        if (!used) {
                err = -ENOMEM;
                dev_err(_vop_dev(vdev), "%s %d err %d\n",
                        __func__, __LINE__, err);
-               goto del_vq;
+               goto unmap;
        }
+
+       vq = vop_new_virtqueue(index, le16_to_cpu(config.num), dev, ctx,
+                              (void __force *)va, vop_notify, callback,
+                              name, used);
+       if (!vq) {
+               err = -ENOMEM;
+               goto free_used;
+       }
+
        vdev->used[index] = dma_map_single(&vpdev->dev, used,
                                            vdev->used_size[index],
                                            DMA_BIDIRECTIONAL);
@@ -360,26 +380,17 @@ static struct virtqueue *vop_find_vq(struct virtio_device *dev,
                err = -ENOMEM;
                dev_err(_vop_dev(vdev), "%s %d err %d\n",
                        __func__, __LINE__, err);
-               goto free_used;
+               goto del_vq;
        }
        writeq(vdev->used[index], &vqconfig->used_address);
-       /*
-        * To reassign the used ring here we are directly accessing
-        * struct vring_virtqueue which is a private data structure
-        * in virtio_ring.c. At the minimum, a BUILD_BUG_ON() in
-        * vring_new_virtqueue() would ensure that
-        *  (&vq->vring == (struct vring *) (&vq->vq + 1));
-        */
-       vr = (struct vring *)(vq + 1);
-       vr->used = used;
 
        vq->priv = vdev;
        return vq;
+del_vq:
+       vring_del_virtqueue(vq);
 free_used:
        free_pages((unsigned long)used,
                   get_order(vdev->used_size[index]));
-del_vq:
-       vring_del_virtqueue(vq);
 unmap:
        vpdev->hw_ops->iounmap(vpdev, vdev->vr[index]);
        return ERR_PTR(err);
@@ -394,16 +405,21 @@ static int vop_find_vqs(struct virtio_device *dev, unsigned nvqs,
        struct _vop_vdev *vdev = to_vopvdev(dev);
        struct vop_device *vpdev = vdev->vpdev;
        struct mic_device_ctrl __iomem *dc = vdev->dc;
-       int i, err, retry;
+       int i, err, retry, queue_idx = 0;
 
        /* We must have this many virtqueues. */
        if (nvqs > ioread8(&vdev->desc->num_vq))
                return -ENOENT;
 
        for (i = 0; i < nvqs; ++i) {
+               if (!names[i]) {
+                       vqs[i] = NULL;
+                       continue;
+               }
+
                dev_dbg(_vop_dev(vdev), "%s: %d: %s\n",
                        __func__, i, names[i]);
-               vqs[i] = vop_find_vq(dev, i, callbacks[i], names[i],
+               vqs[i] = vop_find_vq(dev, queue_idx++, callbacks[i], names[i],
                                     ctx ? ctx[i] : false);
                if (IS_ERR(vqs[i])) {
                        err = PTR_ERR(vqs[i]);
@@ -576,6 +592,8 @@ static int _vop_remove_device(struct mic_device_desc __iomem *d,
        int ret = -1;
 
        if (ioread8(&dc->config_change) == MIC_VIRTIO_PARAM_DEV_REMOVE) {
+               struct device *dev = get_device(&vdev->vdev.dev);
+
                dev_dbg(&vpdev->dev,
                        "%s %d config_change %d type %d vdev %p\n",
                        __func__, __LINE__,
@@ -587,7 +605,7 @@ static int _vop_remove_device(struct mic_device_desc __iomem *d,
                iowrite8(-1, &dc->h2c_vdev_db);
                if (status & VIRTIO_CONFIG_S_DRIVER_OK)
                        wait_for_completion(&vdev->reset_done);
-               put_device(&vdev->vdev.dev);
+               put_device(dev);
                iowrite8(1, &dc->guest_ack);
                dev_dbg(&vpdev->dev, "%s %d guest_ack %d\n",
                        __func__, __LINE__, ioread8(&dc->guest_ack));
index 595ac06..95ff7c5 100644 (file)
@@ -70,8 +70,12 @@ pvpanic_walk_resources(struct acpi_resource *res, void *context)
        struct resource r;
 
        if (acpi_dev_resource_io(res, &r)) {
+#ifdef CONFIG_HAS_IOPORT_MAP
                base = ioport_map(r.start, resource_size(&r));
                return AE_OK;
+#else
+               return AE_ERROR;
+#endif
        } else if (acpi_dev_resource_memory(res, &r)) {
                base = ioremap(r.start, resource_size(&r));
                return AE_OK;
index aef1185..14f3fdb 100644 (file)
@@ -2112,7 +2112,7 @@ static void mmc_blk_mq_req_done(struct mmc_request *mrq)
                if (waiting)
                        wake_up(&mq->wait);
                else
-                       kblockd_schedule_work(&mq->complete_work);
+                       queue_work(mq->card->complete_wq, &mq->complete_work);
 
                return;
        }
@@ -2924,6 +2924,13 @@ static int mmc_blk_probe(struct mmc_card *card)
 
        mmc_fixup_device(card, mmc_blk_fixups);
 
+       card->complete_wq = alloc_workqueue("mmc_complete",
+                                       WQ_MEM_RECLAIM | WQ_HIGHPRI, 0);
+       if (unlikely(!card->complete_wq)) {
+               pr_err("Failed to create mmc completion workqueue");
+               return -ENOMEM;
+       }
+
        md = mmc_blk_alloc(card);
        if (IS_ERR(md))
                return PTR_ERR(md);
@@ -2987,6 +2994,7 @@ static void mmc_blk_remove(struct mmc_card *card)
        pm_runtime_put_noidle(&card->dev);
        mmc_blk_remove_req(md);
        dev_set_drvdata(&card->dev, NULL);
+       destroy_workqueue(card->complete_wq);
 }
 
 static int _mmc_blk_suspend(struct mmc_card *card)
index f57f5de..cf58cca 100644 (file)
@@ -234,7 +234,7 @@ int mmc_of_parse(struct mmc_host *host)
                if (device_property_read_bool(dev, "broken-cd"))
                        host->caps |= MMC_CAP_NEEDS_POLL;
 
-               ret = mmc_gpiod_request_cd(host, "cd", 0, true,
+               ret = mmc_gpiod_request_cd(host, "cd", 0, false,
                                           cd_debounce_delay_ms * 1000,
                                           &cd_gpio_invert);
                if (!ret)
index e26b814..a44ec8b 100644 (file)
@@ -116,7 +116,7 @@ config MMC_RICOH_MMC
 
 config MMC_SDHCI_ACPI
        tristate "SDHCI support for ACPI enumerated SDHCI controllers"
-       depends on MMC_SDHCI && ACPI
+       depends on MMC_SDHCI && ACPI && PCI
        select IOSF_MBI if X86
        help
          This selects support for ACPI enumerated SDHCI controllers,
@@ -978,7 +978,7 @@ config MMC_SDHCI_OMAP
        tristate "TI SDHCI Controller Support"
        depends on MMC_SDHCI_PLTFM && OF
        select THERMAL
-       select TI_SOC_THERMAL
+       imply TI_SOC_THERMAL
        help
          This selects the Secure Digital Host Controller Interface (SDHCI)
          support present in TI's DRA7 SOCs. The controller supports
index 5029352..c9e7aa5 100644 (file)
@@ -1431,6 +1431,8 @@ static int bcm2835_probe(struct platform_device *pdev)
 
 err:
        dev_dbg(dev, "%s -> err %d\n", __func__, ret);
+       if (host->dma_chan_rxtx)
+               dma_release_channel(host->dma_chan_rxtx);
        mmc_free_host(mmc);
 
        return ret;
index ed8f225..aa38b1a 100644 (file)
@@ -1,11 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0
 /*
  * Copyright (C) 2018 Mellanox Technologies.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
  */
 
 #include <linux/bitfield.h>
index c2690c1..2eba507 100644 (file)
@@ -179,6 +179,8 @@ struct meson_host {
        struct sd_emmc_desc *descs;
        dma_addr_t descs_dma_addr;
 
+       int irq;
+
        bool vqmmc_enabled;
 };
 
@@ -738,6 +740,11 @@ static int meson_mmc_clk_phase_tuning(struct mmc_host *mmc, u32 opcode,
 static int meson_mmc_execute_tuning(struct mmc_host *mmc, u32 opcode)
 {
        struct meson_host *host = mmc_priv(mmc);
+       int adj = 0;
+
+       /* enable signal resampling w/o delay */
+       adj = ADJUST_ADJ_EN;
+       writel(adj, host->regs + host->data->adjust);
 
        return meson_mmc_clk_phase_tuning(mmc, opcode, host->rx_clk);
 }
@@ -768,6 +775,9 @@ static void meson_mmc_set_ios(struct mmc_host *mmc, struct mmc_ios *ios)
                if (!IS_ERR(mmc->supply.vmmc))
                        mmc_regulator_set_ocr(mmc, mmc->supply.vmmc, ios->vdd);
 
+               /* disable signal resampling */
+               writel(0, host->regs + host->data->adjust);
+
                /* Reset rx phase */
                clk_set_phase(host->rx_clk, 0);
 
@@ -1166,7 +1176,7 @@ static int meson_mmc_get_cd(struct mmc_host *mmc)
 
 static void meson_mmc_cfg_init(struct meson_host *host)
 {
-       u32 cfg = 0, adj = 0;
+       u32 cfg = 0;
 
        cfg |= FIELD_PREP(CFG_RESP_TIMEOUT_MASK,
                          ilog2(SD_EMMC_CFG_RESP_TIMEOUT));
@@ -1177,10 +1187,6 @@ static void meson_mmc_cfg_init(struct meson_host *host)
        cfg |= CFG_ERR_ABORT;
 
        writel(cfg, host->regs + SD_EMMC_CFG);
-
-       /* enable signal resampling w/o delay */
-       adj = ADJUST_ADJ_EN;
-       writel(adj, host->regs + host->data->adjust);
 }
 
 static int meson_mmc_card_busy(struct mmc_host *mmc)
@@ -1231,7 +1237,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
        struct resource *res;
        struct meson_host *host;
        struct mmc_host *mmc;
-       int ret, irq;
+       int ret;
 
        mmc = mmc_alloc_host(sizeof(struct meson_host), &pdev->dev);
        if (!mmc)
@@ -1276,8 +1282,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
                goto free_host;
        }
 
-       irq = platform_get_irq(pdev, 0);
-       if (irq <= 0) {
+       host->irq = platform_get_irq(pdev, 0);
+       if (host->irq <= 0) {
                dev_err(&pdev->dev, "failed to get interrupt resource.\n");
                ret = -EINVAL;
                goto free_host;
@@ -1331,9 +1337,9 @@ static int meson_mmc_probe(struct platform_device *pdev)
        writel(IRQ_CRC_ERR | IRQ_TIMEOUTS | IRQ_END_OF_CHAIN,
               host->regs + SD_EMMC_IRQ_EN);
 
-       ret = devm_request_threaded_irq(&pdev->dev, irq, meson_mmc_irq,
-                                       meson_mmc_irq_thread, IRQF_SHARED,
-                                       NULL, host);
+       ret = request_threaded_irq(host->irq, meson_mmc_irq,
+                                  meson_mmc_irq_thread, IRQF_SHARED,
+                                  dev_name(&pdev->dev), host);
        if (ret)
                goto err_init_clk;
 
@@ -1351,7 +1357,7 @@ static int meson_mmc_probe(struct platform_device *pdev)
        if (host->bounce_buf == NULL) {
                dev_err(host->dev, "Unable to map allocate DMA bounce buffer.\n");
                ret = -ENOMEM;
-               goto err_init_clk;
+               goto err_free_irq;
        }
 
        host->descs = dma_alloc_coherent(host->dev, SD_EMMC_DESC_BUF_LEN,
@@ -1370,6 +1376,8 @@ static int meson_mmc_probe(struct platform_device *pdev)
 err_bounce_buf:
        dma_free_coherent(host->dev, host->bounce_buf_size,
                          host->bounce_buf, host->bounce_dma_addr);
+err_free_irq:
+       free_irq(host->irq, host);
 err_init_clk:
        clk_disable_unprepare(host->mmc_clk);
 err_core_clk:
@@ -1387,6 +1395,7 @@ static int meson_mmc_remove(struct platform_device *pdev)
 
        /* disable interrupts */
        writel(0, host->regs + SD_EMMC_IRQ_EN);
+       free_irq(host->irq, host);
 
        dma_free_coherent(host->dev, SD_EMMC_DESC_BUF_LEN,
                          host->descs, host->descs_dma_addr);
index 8afeaf8..833ef05 100644 (file)
@@ -846,7 +846,7 @@ static void msdc_set_mclk(struct msdc_host *host, unsigned char timing, u32 hz)
 
        if (timing == MMC_TIMING_MMC_HS400 &&
            host->dev_comp->hs400_tune)
-               sdr_set_field(host->base + PAD_CMD_TUNE,
+               sdr_set_field(host->base + tune_reg,
                              MSDC_PAD_TUNE_CMDRRDLY,
                              host->hs400_cmd_int_delay);
        dev_dbg(host->dev, "sclk: %d, timing: %d\n", host->mmc->actual_clock,
index 0db9905..9d12c06 100644 (file)
@@ -296,7 +296,10 @@ static int sdhci_iproc_probe(struct platform_device *pdev)
 
        iproc_host->data = iproc_data;
 
-       mmc_of_parse(host->mmc);
+       ret = mmc_of_parse(host->mmc);
+       if (ret)
+               goto err;
+
        sdhci_get_property(pdev);
 
        host->mmc->caps |= iproc_host->data->mmc_caps;
index a22e11a..eba9bcc 100644 (file)
@@ -3763,8 +3763,9 @@ int sdhci_setup_host(struct sdhci_host *host)
                 * Use zalloc to zero the reserved high 32-bits of 128-bit
                 * descriptors so that they never need to be written.
                 */
-               buf = dma_zalloc_coherent(mmc_dev(mmc), host->align_buffer_sz +
-                                        host->adma_table_sz, &dma, GFP_KERNEL);
+               buf = dma_alloc_coherent(mmc_dev(mmc),
+                                        host->align_buffer_sz + host->adma_table_sz,
+                                        &dma, GFP_KERNEL);
                if (!buf) {
                        pr_warn("%s: Unable to allocate ADMA buffers - falling back to standard DMA\n",
                                mmc_hostname(mmc));
index 279e326..70fadc9 100644 (file)
@@ -1399,13 +1399,37 @@ static int sunxi_mmc_probe(struct platform_device *pdev)
        mmc->caps              |= MMC_CAP_MMC_HIGHSPEED | MMC_CAP_SD_HIGHSPEED |
                                  MMC_CAP_ERASE | MMC_CAP_SDIO_IRQ;
 
-       if (host->cfg->clk_delays || host->use_new_timings)
+       /*
+        * Some H5 devices do not have signal traces precise enough to
+        * use HS DDR mode for their eMMC chips.
+        *
+        * We still enable HS DDR modes for all the other controller
+        * variants that support them.
+        */
+       if ((host->cfg->clk_delays || host->use_new_timings) &&
+           !of_device_is_compatible(pdev->dev.of_node,
+                                    "allwinner,sun50i-h5-emmc"))
                mmc->caps      |= MMC_CAP_1_8V_DDR | MMC_CAP_3_3V_DDR;
 
        ret = mmc_of_parse(mmc);
        if (ret)
                goto error_free_dma;
 
+       /*
+        * If we don't support delay chains in the SoC, we can't use any
+        * of the higher speed modes. Mask them out in case the device
+        * tree specifies the properties for them, which gets added to
+        * the caps by mmc_of_parse() above.
+        */
+       if (!(host->cfg->clk_delays || host->use_new_timings)) {
+               mmc->caps &= ~(MMC_CAP_3_3V_DDR | MMC_CAP_1_8V_DDR |
+                              MMC_CAP_1_2V_DDR | MMC_CAP_UHS);
+               mmc->caps2 &= ~MMC_CAP2_HS200;
+       }
+
+       /* TODO: This driver doesn't support HS400 mode yet */
+       mmc->caps2 &= ~MMC_CAP2_HS400;
+
        ret = sunxi_mmc_init_host(host);
        if (ret)
                goto error_free_dma;
index 22f753e..83f88b8 100644 (file)
@@ -212,7 +212,7 @@ static int powernv_flash_set_driver_info(struct device *dev,
         * Going to have to check what details I need to set and how to
         * get them
         */
-       mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFn", dev->of_node);
+       mtd->name = devm_kasprintf(dev, GFP_KERNEL, "%pOFP", dev->of_node);
        mtd->type = MTD_NORFLASH;
        mtd->flags = MTD_WRITEABLE;
        mtd->size = size;
index 21e3cdc..3ef01ba 100644 (file)
@@ -507,6 +507,7 @@ static int mtd_nvmem_add(struct mtd_info *mtd)
 {
        struct nvmem_config config = {};
 
+       config.id = -1;
        config.dev = &mtd->dev;
        config.name = mtd->name;
        config.owner = THIS_MODULE;
@@ -522,7 +523,7 @@ static int mtd_nvmem_add(struct mtd_info *mtd)
        mtd->nvmem = nvmem_register(&config);
        if (IS_ERR(mtd->nvmem)) {
                /* Just ignore if there is no NVMEM support in the kernel */
-               if (PTR_ERR(mtd->nvmem) == -ENOSYS) {
+               if (PTR_ERR(mtd->nvmem) == -EOPNOTSUPP) {
                        mtd->nvmem = NULL;
                } else {
                        dev_err(&mtd->dev, "Failed to register NVMEM device\n");
index 9887bda..b31c868 100644 (file)
@@ -7,7 +7,7 @@
 extern struct mutex mtd_table_mutex;
 
 struct mtd_info *__mtd_next_device(int i);
-int add_mtd_device(struct mtd_info *mtd);
+int __must_check add_mtd_device(struct mtd_info *mtd);
 int del_mtd_device(struct mtd_info *mtd);
 int add_mtd_partitions(struct mtd_info *, const struct mtd_partition *, int);
 int del_mtd_partitions(struct mtd_info *);
index b6af41b..37f174c 100644 (file)
@@ -480,6 +480,10 @@ static struct mtd_part *allocate_partition(struct mtd_info *parent,
                /* let's register it anyway to preserve ordering */
                slave->offset = 0;
                slave->mtd.size = 0;
+
+               /* Initialize ->erasesize to make add_mtd_device() happy. */
+               slave->mtd.erasesize = parent->erasesize;
+
                printk(KERN_ERR"mtd: partition \"%s\" is out of reach -- disabled\n",
                        part->name);
                goto out_register;
@@ -618,10 +622,21 @@ int mtd_add_partition(struct mtd_info *parent, const char *name,
        list_add(&new->list, &mtd_partitions);
        mutex_unlock(&mtd_partitions_mutex);
 
-       add_mtd_device(&new->mtd);
+       ret = add_mtd_device(&new->mtd);
+       if (ret)
+               goto err_remove_part;
 
        mtd_add_partition_attrs(new);
 
+       return 0;
+
+err_remove_part:
+       mutex_lock(&mtd_partitions_mutex);
+       list_del(&new->list);
+       mutex_unlock(&mtd_partitions_mutex);
+
+       free_partition(new);
+
        return ret;
 }
 EXPORT_SYMBOL_GPL(mtd_add_partition);
@@ -712,22 +727,31 @@ int add_mtd_partitions(struct mtd_info *master,
 {
        struct mtd_part *slave;
        uint64_t cur_offset = 0;
-       int i;
+       int i, ret;
 
        printk(KERN_NOTICE "Creating %d MTD partitions on \"%s\":\n", nbparts, master->name);
 
        for (i = 0; i < nbparts; i++) {
                slave = allocate_partition(master, parts + i, i, cur_offset);
                if (IS_ERR(slave)) {
-                       del_mtd_partitions(master);
-                       return PTR_ERR(slave);
+                       ret = PTR_ERR(slave);
+                       goto err_del_partitions;
                }
 
                mutex_lock(&mtd_partitions_mutex);
                list_add(&slave->list, &mtd_partitions);
                mutex_unlock(&mtd_partitions_mutex);
 
-               add_mtd_device(&slave->mtd);
+               ret = add_mtd_device(&slave->mtd);
+               if (ret) {
+                       mutex_lock(&mtd_partitions_mutex);
+                       list_del(&slave->list);
+                       mutex_unlock(&mtd_partitions_mutex);
+
+                       free_partition(slave);
+                       goto err_del_partitions;
+               }
+
                mtd_add_partition_attrs(slave);
                /* Look for subpartitions */
                parse_mtd_partitions(&slave->mtd, parts[i].types, NULL);
@@ -736,6 +760,11 @@ int add_mtd_partitions(struct mtd_info *master,
        }
 
        return 0;
+
+err_del_partitions:
+       del_mtd_partitions(master);
+
+       return ret;
 }
 
 static DEFINE_SPINLOCK(part_parser_lock);
index eebac35..6e8edc9 100644 (file)
@@ -1322,7 +1322,7 @@ int denali_init(struct denali_nand_info *denali)
        }
 
        /* clk rate info is needed for setup_data_interface */
-       if (denali->clk_rate && denali->clk_x_rate)
+       if (!denali->clk_rate || !denali->clk_x_rate)
                chip->options |= NAND_KEEP_TIMINGS;
 
        chip->legacy.dummy_controller.ops = &denali_controller_ops;
index 325b441..c9149a3 100644 (file)
@@ -593,23 +593,6 @@ static void fsmc_write_buf_dma(struct fsmc_nand_data *host, const u8 *buf,
        dma_xfer(host, (void *)buf, len, DMA_TO_DEVICE);
 }
 
-/* fsmc_select_chip - assert or deassert nCE */
-static void fsmc_ce_ctrl(struct fsmc_nand_data *host, bool assert)
-{
-       u32 pc = readl(host->regs_va + FSMC_PC);
-
-       if (!assert)
-               writel_relaxed(pc & ~FSMC_ENABLE, host->regs_va + FSMC_PC);
-       else
-               writel_relaxed(pc | FSMC_ENABLE, host->regs_va + FSMC_PC);
-
-       /*
-        * nCE line changes must be applied before returning from this
-        * function.
-        */
-       mb();
-}
-
 /*
  * fsmc_exec_op - hook called by the core to execute NAND operations
  *
@@ -627,8 +610,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
 
        pr_debug("Executing operation [%d instructions]:\n", op->ninstrs);
 
-       fsmc_ce_ctrl(host, true);
-
        for (op_id = 0; op_id < op->ninstrs; op_id++) {
                instr = &op->instrs[op_id];
 
@@ -686,8 +667,6 @@ static int fsmc_exec_op(struct nand_chip *chip, const struct nand_operation *op,
                }
        }
 
-       fsmc_ce_ctrl(host, false);
-
        return ret;
 }
 
index bd4cfac..a4768df 100644 (file)
@@ -155,9 +155,10 @@ int gpmi_init(struct gpmi_nand_data *this)
 
        /*
         * Reset BCH here, too. We got failures otherwise :(
-        * See later BCH reset for explanation of MX23 handling
+        * See later BCH reset for explanation of MX23 and MX28 handling
         */
-       ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
+       ret = gpmi_reset_block(r->bch_regs,
+                              GPMI_IS_MX23(this) || GPMI_IS_MX28(this));
        if (ret)
                goto err_out;
 
@@ -263,12 +264,10 @@ int bch_set_geometry(struct gpmi_nand_data *this)
        /*
        * Due to erratum #2847 of the MX23, the BCH cannot be soft reset on this
        * chip, otherwise it will lock up. So we skip resetting BCH on the MX23.
-       * On the other hand, the MX28 needs the reset, because one case has been
-       * seen where the BCH produced ECC errors constantly after 10000
-       * consecutive reboots. The latter case has not been seen on the MX23
-       * yet, still we don't know if it could happen there as well.
+       * and MX28.
        */
-       ret = gpmi_reset_block(r->bch_regs, GPMI_IS_MX23(this));
+       ret = gpmi_reset_block(r->bch_regs,
+                              GPMI_IS_MX23(this) || GPMI_IS_MX28(this));
        if (ret)
                goto err_out;
 
index f92ae5a..9526d5b 100644 (file)
@@ -260,7 +260,7 @@ static int jz_nand_correct_ecc_rs(struct nand_chip *chip, uint8_t *dat,
 }
 
 static int jz_nand_ioremap_resource(struct platform_device *pdev,
-       const char *name, struct resource **res, void *__iomem *base)
+       const char *name, struct resource **res, void __iomem **base)
 {
        int ret;
 
index cca4b24..839494a 100644 (file)
@@ -410,6 +410,7 @@ static int nand_check_wp(struct nand_chip *chip)
 
 /**
  * nand_fill_oob - [INTERN] Transfer client buffer to oob
+ * @chip: NAND chip object
  * @oob: oob data buffer
  * @len: oob data write length
  * @ops: oob ops structure
index 1b722fe..19a2b56 100644 (file)
@@ -158,7 +158,7 @@ static u32 add_marker_len(struct nand_bbt_descr *td)
 
 /**
  * read_bbt - [GENERIC] Read the bad block table starting from page
- * @chip: NAND chip object
+ * @this: NAND chip object
  * @buf: temporary buffer
  * @page: the starting page
  * @num: the number of bbt descriptors to read
index 46c62a3..920e737 100644 (file)
@@ -2833,6 +2833,16 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
        if (ret)
                return ret;
 
+       if (nandc->props->is_bam) {
+               free_bam_transaction(nandc);
+               nandc->bam_txn = alloc_bam_transaction(nandc);
+               if (!nandc->bam_txn) {
+                       dev_err(nandc->dev,
+                               "failed to allocate bam transaction\n");
+                       return -ENOMEM;
+               }
+       }
+
        ret = mtd_device_register(mtd, NULL, 0);
        if (ret)
                nand_cleanup(chip);
@@ -2847,16 +2857,6 @@ static int qcom_probe_nand_devices(struct qcom_nand_controller *nandc)
        struct qcom_nand_host *host;
        int ret;
 
-       if (nandc->props->is_bam) {
-               free_bam_transaction(nandc);
-               nandc->bam_txn = alloc_bam_transaction(nandc);
-               if (!nandc->bam_txn) {
-                       dev_err(nandc->dev,
-                               "failed to allocate bam transaction\n");
-                       return -ENOMEM;
-               }
-       }
-
        for_each_available_child_of_node(dn, child) {
                host = devm_kzalloc(dev, sizeof(*host), GFP_KERNEL);
                if (!host) {
index 479c2f2..fa87ae2 100644 (file)
@@ -304,24 +304,30 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
        struct nand_device *nand = spinand_to_nand(spinand);
        struct mtd_info *mtd = nanddev_to_mtd(nand);
        struct nand_page_io_req adjreq = *req;
-       unsigned int nbytes = 0;
-       void *buf = NULL;
+       void *buf = spinand->databuf;
+       unsigned int nbytes;
        u16 column = 0;
        int ret;
 
-       memset(spinand->databuf, 0xff,
-              nanddev_page_size(nand) +
-              nanddev_per_page_oobsize(nand));
+       /*
+        * Looks like PROGRAM LOAD (AKA write cache) does not necessarily reset
+        * the cache content to 0xFF (depends on vendor implementation), so we
+        * must fill the page cache entirely even if we only want to program
+        * the data portion of the page, otherwise we might corrupt the BBM or
+        * user data previously programmed in OOB area.
+        */
+       nbytes = nanddev_page_size(nand) + nanddev_per_page_oobsize(nand);
+       memset(spinand->databuf, 0xff, nbytes);
+       adjreq.dataoffs = 0;
+       adjreq.datalen = nanddev_page_size(nand);
+       adjreq.databuf.out = spinand->databuf;
+       adjreq.ooblen = nanddev_per_page_oobsize(nand);
+       adjreq.ooboffs = 0;
+       adjreq.oobbuf.out = spinand->oobbuf;
 
-       if (req->datalen) {
+       if (req->datalen)
                memcpy(spinand->databuf + req->dataoffs, req->databuf.out,
                       req->datalen);
-               adjreq.dataoffs = 0;
-               adjreq.datalen = nanddev_page_size(nand);
-               adjreq.databuf.out = spinand->databuf;
-               nbytes = adjreq.datalen;
-               buf = spinand->databuf;
-       }
 
        if (req->ooblen) {
                if (req->mode == MTD_OPS_AUTO_OOB)
@@ -332,14 +338,6 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
                else
                        memcpy(spinand->oobbuf + req->ooboffs, req->oobbuf.out,
                               req->ooblen);
-
-               adjreq.ooblen = nanddev_per_page_oobsize(nand);
-               adjreq.ooboffs = 0;
-               nbytes += nanddev_per_page_oobsize(nand);
-               if (!buf) {
-                       buf = spinand->oobbuf;
-                       column = nanddev_page_size(nand);
-               }
        }
 
        spinand_cache_op_adjust_colum(spinand, &adjreq, &column);
@@ -370,8 +368,8 @@ static int spinand_write_to_cache_op(struct spinand_device *spinand,
 
                /*
                 * We need to use the RANDOM LOAD CACHE operation if there's
-                * more than one iteration, because the LOAD operation resets
-                * the cache to 0xff.
+                * more than one iteration, because the LOAD operation might
+                * reset the cache to 0xff.
                 */
                if (nbytes) {
                        column = op.addr.val;
@@ -1018,11 +1016,11 @@ static int spinand_init(struct spinand_device *spinand)
        for (i = 0; i < nand->memorg.ntargets; i++) {
                ret = spinand_select_target(spinand, i);
                if (ret)
-                       goto err_free_bufs;
+                       goto err_manuf_cleanup;
 
                ret = spinand_lock_block(spinand, BL_ALL_UNLOCKED);
                if (ret)
-                       goto err_free_bufs;
+                       goto err_manuf_cleanup;
        }
 
        ret = nanddev_init(nand, &spinand_ops, THIS_MODULE);
index 6371958..21bf8ac 100644 (file)
@@ -197,9 +197,9 @@ config VXLAN
 
 config GENEVE
        tristate "Generic Network Virtualization Encapsulation"
-       depends on INET && NET_UDP_TUNNEL
+       depends on INET
        depends on IPV6 || !IPV6
-       select NET_IP_TUNNEL
+       select NET_UDP_TUNNEL
        select GRO_CELLS
        ---help---
          This allows one to create geneve virtual interfaces that provide
@@ -519,7 +519,7 @@ config NET_FAILOVER
          and destroy a failover master netdev and manages a primary and
          standby slave netdevs that get registered via the generic failover
          infrastructure. This can be used by paravirtual drivers to enable
-         an alternate low latency datapath. It alsoenables live migration of
+         an alternate low latency datapath. It also enables live migration of
          a VM with direct attached VF by failing over to the paravirtual
          datapath when the VF is unplugged.
 
index a9d597f..537c90c 100644 (file)
@@ -1183,29 +1183,22 @@ static rx_handler_result_t bond_handle_frame(struct sk_buff **pskb)
                }
        }
 
-       /* Link-local multicast packets should be passed to the
-        * stack on the link they arrive as well as pass them to the
-        * bond-master device. These packets are mostly usable when
-        * stack receives it with the link on which they arrive
-        * (e.g. LLDP) they also must be available on master. Some of
-        * the use cases include (but are not limited to): LLDP agents
-        * that must be able to operate both on enslaved interfaces as
-        * well as on bonds themselves; linux bridges that must be able
-        * to process/pass BPDUs from attached bonds when any kind of
-        * STP version is enabled on the network.
+       /*
+        * For packets determined by bond_should_deliver_exact_match() call to
+        * be suppressed we want to make an exception for link-local packets.
+        * This is necessary for e.g. LLDP daemons to be able to monitor
+        * inactive slave links without being forced to bind to them
+        * explicitly.
+        *
+        * At the same time, packets that are passed to the bonding master
+        * (including link-local ones) can have their originating interface
+        * determined via PACKET_ORIGDEV socket option.
         */
-       if (is_link_local_ether_addr(eth_hdr(skb)->h_dest)) {
-               struct sk_buff *nskb = skb_clone(skb, GFP_ATOMIC);
-
-               if (nskb) {
-                       nskb->dev = bond->dev;
-                       nskb->queue_mapping = 0;
-                       netif_rx(nskb);
-               }
-               return RX_HANDLER_PASS;
-       }
-       if (bond_should_deliver_exact_match(skb, slave, bond))
+       if (bond_should_deliver_exact_match(skb, slave, bond)) {
+               if (is_link_local_ether_addr(eth_hdr(skb)->h_dest))
+                       return RX_HANDLER_PASS;
                return RX_HANDLER_EXACT;
+       }
 
        skb->dev = bond->dev;
 
@@ -1963,6 +1956,9 @@ static int __bond_release_one(struct net_device *bond_dev,
        if (!bond_has_slaves(bond)) {
                bond_set_carrier(bond);
                eth_hw_addr_random(bond_dev);
+               bond->nest_level = SINGLE_DEPTH_NESTING;
+       } else {
+               bond->nest_level = dev_get_nest_level(bond_dev) + 1;
        }
 
        unblock_netpoll_tx();
index a0f954f..44e6c7b 100644 (file)
@@ -257,10 +257,7 @@ static int handle_tx(struct ser_device *ser)
                if (skb->len == 0) {
                        struct sk_buff *tmp = skb_dequeue(&ser->head);
                        WARN_ON(tmp != skb);
-                       if (in_interrupt())
-                               dev_kfree_skb_irq(skb);
-                       else
-                               kfree_skb(skb);
+                       dev_consume_skb_any(skb);
                }
        }
        /* Send flow off if queue is empty */
index 3b3f88f..c05e4d5 100644 (file)
@@ -480,8 +480,6 @@ EXPORT_SYMBOL_GPL(can_put_echo_skb);
 struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8 *len_ptr)
 {
        struct can_priv *priv = netdev_priv(dev);
-       struct sk_buff *skb = priv->echo_skb[idx];
-       struct canfd_frame *cf;
 
        if (idx >= priv->echo_skb_max) {
                netdev_err(dev, "%s: BUG! Trying to access can_priv::echo_skb out of bounds (%u/max %u)\n",
@@ -489,20 +487,21 @@ struct sk_buff *__can_get_echo_skb(struct net_device *dev, unsigned int idx, u8
                return NULL;
        }
 
-       if (!skb) {
-               netdev_err(dev, "%s: BUG! Trying to echo non existing skb: can_priv::echo_skb[%u]\n",
-                          __func__, idx);
-               return NULL;
-       }
+       if (priv->echo_skb[idx]) {
+               /* Using "struct canfd_frame::len" for the frame
+                * length is supported on both CAN and CANFD frames.
+                */
+               struct sk_buff *skb = priv->echo_skb[idx];
+               struct canfd_frame *cf = (struct canfd_frame *)skb->data;
+               u8 len = cf->len;
 
-       /* Using "struct canfd_frame::len" for the frame
-        * length is supported on both CAN and CANFD frames.
-        */
-       cf = (struct canfd_frame *)skb->data;
-       *len_ptr = cf->len;
-       priv->echo_skb[idx] = NULL;
+               *len_ptr = len;
+               priv->echo_skb[idx] = NULL;
 
-       return skb;
+               return skb;
+       }
+
+       return NULL;
 }
 
 /*
index 0f36eaf..1c66fb2 100644 (file)
@@ -1106,7 +1106,7 @@ static int flexcan_chip_start(struct net_device *dev)
                }
        } else {
                /* clear and invalidate unused mailboxes first */
-               for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i <= priv->mb_count; i++) {
+               for (i = FLEXCAN_TX_MB_RESERVED_OFF_FIFO; i < priv->mb_count; i++) {
                        mb = flexcan_get_mb(priv, i);
                        priv->write(FLEXCAN_MB_CODE_RX_INACTIVE,
                                    &mb->can_ctrl);
@@ -1432,7 +1432,7 @@ static int flexcan_setup_stop_mode(struct platform_device *pdev)
        gpr_np = of_find_node_by_phandle(phandle);
        if (!gpr_np) {
                dev_dbg(&pdev->dev, "could not find gpr node by phandle\n");
-               return PTR_ERR(gpr_np);
+               return -ENODEV;
        }
 
        priv = netdev_priv(dev);
index 0e4bbdc..c76892a 100644 (file)
@@ -344,7 +344,8 @@ static void b53_set_forwarding(struct b53_device *dev, int enable)
        b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_CTRL, mgmt);
 }
 
-static void b53_enable_vlan(struct b53_device *dev, bool enable)
+static void b53_enable_vlan(struct b53_device *dev, bool enable,
+                           bool enable_filtering)
 {
        u8 mgmt, vc0, vc1, vc4 = 0, vc5;
 
@@ -369,8 +370,13 @@ static void b53_enable_vlan(struct b53_device *dev, bool enable)
                vc0 |= VC0_VLAN_EN | VC0_VID_CHK_EN | VC0_VID_HASH_VID;
                vc1 |= VC1_RX_MCST_UNTAG_EN | VC1_RX_MCST_FWD_EN;
                vc4 &= ~VC4_ING_VID_CHECK_MASK;
-               vc4 |= VC4_ING_VID_VIO_DROP << VC4_ING_VID_CHECK_S;
-               vc5 |= VC5_DROP_VTABLE_MISS;
+               if (enable_filtering) {
+                       vc4 |= VC4_ING_VID_VIO_DROP << VC4_ING_VID_CHECK_S;
+                       vc5 |= VC5_DROP_VTABLE_MISS;
+               } else {
+                       vc4 |= VC4_ING_VID_VIO_FWD << VC4_ING_VID_CHECK_S;
+                       vc5 &= ~VC5_DROP_VTABLE_MISS;
+               }
 
                if (is5325(dev))
                        vc0 &= ~VC0_RESERVED_1;
@@ -420,6 +426,9 @@ static void b53_enable_vlan(struct b53_device *dev, bool enable)
        }
 
        b53_write8(dev, B53_CTRL_PAGE, B53_SWITCH_MODE, mgmt);
+
+       dev->vlan_enabled = enable;
+       dev->vlan_filtering_enabled = enable_filtering;
 }
 
 static int b53_set_jumbo(struct b53_device *dev, bool enable, bool allow_10_100)
@@ -632,25 +641,35 @@ static void b53_enable_mib(struct b53_device *dev)
        b53_write8(dev, B53_MGMT_PAGE, B53_GLOBAL_CONFIG, gc);
 }
 
+static u16 b53_default_pvid(struct b53_device *dev)
+{
+       if (is5325(dev) || is5365(dev))
+               return 1;
+       else
+               return 0;
+}
+
 int b53_configure_vlan(struct dsa_switch *ds)
 {
        struct b53_device *dev = ds->priv;
        struct b53_vlan vl = { 0 };
-       int i;
+       int i, def_vid;
+
+       def_vid = b53_default_pvid(dev);
 
        /* clear all vlan entries */
        if (is5325(dev) || is5365(dev)) {
-               for (i = 1; i < dev->num_vlans; i++)
+               for (i = def_vid; i < dev->num_vlans; i++)
                        b53_set_vlan_entry(dev, i, &vl);
        } else {
                b53_do_vlan_op(dev, VTA_CMD_CLEAR);
        }
 
-       b53_enable_vlan(dev, false);
+       b53_enable_vlan(dev, false, dev->vlan_filtering_enabled);
 
        b53_for_each_port(dev, i)
                b53_write16(dev, B53_VLAN_PAGE,
-                           B53_VLAN_PORT_DEF_TAG(i), 1);
+                           B53_VLAN_PORT_DEF_TAG(i), def_vid);
 
        if (!is5325(dev) && !is5365(dev))
                b53_set_jumbo(dev, dev->enable_jumbo, false);
@@ -1255,6 +1274,46 @@ EXPORT_SYMBOL(b53_phylink_mac_link_up);
 
 int b53_vlan_filtering(struct dsa_switch *ds, int port, bool vlan_filtering)
 {
+       struct b53_device *dev = ds->priv;
+       struct net_device *bridge_dev;
+       unsigned int i;
+       u16 pvid, new_pvid;
+
+       /* Handle the case were multiple bridges span the same switch device
+        * and one of them has a different setting than what is being requested
+        * which would be breaking filtering semantics for any of the other
+        * bridge devices.
+        */
+       b53_for_each_port(dev, i) {
+               bridge_dev = dsa_to_port(ds, i)->bridge_dev;
+               if (bridge_dev &&
+                   bridge_dev != dsa_to_port(ds, port)->bridge_dev &&
+                   br_vlan_enabled(bridge_dev) != vlan_filtering) {
+                       netdev_err(bridge_dev,
+                                  "VLAN filtering is global to the switch!\n");
+                       return -EINVAL;
+               }
+       }
+
+       b53_read16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port), &pvid);
+       new_pvid = pvid;
+       if (dev->vlan_filtering_enabled && !vlan_filtering) {
+               /* Filtering is currently enabled, use the default PVID since
+                * the bridge does not expect tagging anymore
+                */
+               dev->ports[port].pvid = pvid;
+               new_pvid = b53_default_pvid(dev);
+       } else if (!dev->vlan_filtering_enabled && vlan_filtering) {
+               /* Filtering is currently disabled, restore the previous PVID */
+               new_pvid = dev->ports[port].pvid;
+       }
+
+       if (pvid != new_pvid)
+               b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port),
+                           new_pvid);
+
+       b53_enable_vlan(dev, dev->vlan_enabled, vlan_filtering);
+
        return 0;
 }
 EXPORT_SYMBOL(b53_vlan_filtering);
@@ -1270,7 +1329,7 @@ int b53_vlan_prepare(struct dsa_switch *ds, int port,
        if (vlan->vid_end > dev->num_vlans)
                return -ERANGE;
 
-       b53_enable_vlan(dev, true);
+       b53_enable_vlan(dev, true, dev->vlan_filtering_enabled);
 
        return 0;
 }
@@ -1300,7 +1359,7 @@ void b53_vlan_add(struct dsa_switch *ds, int port,
                b53_fast_age_vlan(dev, vid);
        }
 
-       if (pvid) {
+       if (pvid && !dsa_is_cpu_port(ds, port)) {
                b53_write16(dev, B53_VLAN_PAGE, B53_VLAN_PORT_DEF_TAG(port),
                            vlan->vid_end);
                b53_fast_age_vlan(dev, vid);
@@ -1326,12 +1385,8 @@ int b53_vlan_del(struct dsa_switch *ds, int port,
 
                vl->members &= ~BIT(port);
 
-               if (pvid == vid) {
-                       if (is5325(dev) || is5365(dev))
-                               pvid = 1;
-                       else
-                               pvid = 0;
-               }
+               if (pvid == vid)
+                       pvid = b53_default_pvid(dev);
 
                if (untagged && !dsa_is_cpu_port(ds, port))
                        vl->untag &= ~(BIT(port));
@@ -1644,10 +1699,7 @@ void b53_br_leave(struct dsa_switch *ds, int port, struct net_device *br)
        b53_write16(dev, B53_PVLAN_PAGE, B53_PVLAN_PORT_MASK(port), pvlan);
        dev->ports[port].vlan_ctl_mask = pvlan;
 
-       if (is5325(dev) || is5365(dev))
-               pvid = 1;
-       else
-               pvid = 0;
+       pvid = b53_default_pvid(dev);
 
        /* Make this port join all VLANs without VLAN entries */
        if (is58xx(dev)) {
index ec79648..4dc7ee3 100644 (file)
@@ -91,6 +91,7 @@ enum {
 struct b53_port {
        u16             vlan_ctl_mask;
        struct ethtool_eee eee;
+       u16             pvid;
 };
 
 struct b53_vlan {
@@ -137,6 +138,8 @@ struct b53_device {
 
        unsigned int num_vlans;
        struct b53_vlan *vlans;
+       bool vlan_enabled;
+       bool vlan_filtering_enabled;
        unsigned int num_ports;
        struct b53_port *ports;
 };
index 90f5142..d9c56a7 100644 (file)
@@ -511,9 +511,6 @@ static void b53_srab_prepare_irq(struct platform_device *pdev)
        /* Clear all pending interrupts */
        writel(0xffffffff, priv->regs + B53_SRAB_INTR);
 
-       if (dev->pdata && dev->pdata->chip_id != BCM58XX_DEVICE_ID)
-               return;
-
        for (i = 0; i < B53_N_PORTS; i++) {
                port = &priv->port_intrs[i];
 
index 361fbde..14138d4 100644 (file)
@@ -690,7 +690,7 @@ static int bcm_sf2_sw_suspend(struct dsa_switch *ds)
         * port, the other ones have already been disabled during
         * bcm_sf2_sw_setup
         */
-       for (port = 0; port < DSA_MAX_PORTS; port++) {
+       for (port = 0; port < ds->num_ports; port++) {
                if (dsa_is_user_port(ds, port) || dsa_is_cpu_port(ds, port))
                        bcm_sf2_port_disable(ds, port, NULL);
        }
@@ -726,10 +726,11 @@ static void bcm_sf2_sw_get_wol(struct dsa_switch *ds, int port,
 {
        struct net_device *p = ds->ports[port].cpu_dp->master;
        struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
-       struct ethtool_wolinfo pwol;
+       struct ethtool_wolinfo pwol = { };
 
        /* Get the parent device WoL settings */
-       p->ethtool_ops->get_wol(p, &pwol);
+       if (p->ethtool_ops->get_wol)
+               p->ethtool_ops->get_wol(p, &pwol);
 
        /* Advertise the parent device supported settings */
        wol->supported = pwol.supported;
@@ -750,9 +751,10 @@ static int bcm_sf2_sw_set_wol(struct dsa_switch *ds, int port,
        struct net_device *p = ds->ports[port].cpu_dp->master;
        struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
        s8 cpu_port = ds->ports[port].cpu_dp->index;
-       struct ethtool_wolinfo pwol;
+       struct ethtool_wolinfo pwol =  { };
 
-       p->ethtool_ops->get_wol(p, &pwol);
+       if (p->ethtool_ops->get_wol)
+               p->ethtool_ops->get_wol(p, &pwol);
        if (wol->wolopts & ~pwol.supported)
                return -EINVAL;
 
index 3b12e2d..8a5111f 100644 (file)
@@ -7,7 +7,6 @@
 
 #include <linux/delay.h>
 #include <linux/export.h>
-#include <linux/gpio.h>
 #include <linux/gpio/consumer.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -15,7 +14,6 @@
 #include <linux/phy.h>
 #include <linux/etherdevice.h>
 #include <linux/if_bridge.h>
-#include <linux/of_gpio.h>
 #include <linux/of_net.h>
 #include <net/dsa.h>
 #include <net/switchdev.h>
index 74547f4..a8a2c72 100644 (file)
@@ -18,7 +18,6 @@
 #include <linux/mfd/syscon.h>
 #include <linux/module.h>
 #include <linux/netdevice.h>
-#include <linux/of_gpio.h>
 #include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include <linux/of_platform.h>
index 8a517d8..12fd7ce 100644 (file)
@@ -261,6 +261,7 @@ static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)
        unsigned int sub_irq;
        unsigned int n;
        u16 reg;
+       u16 ctl1;
        int err;
 
        mutex_lock(&chip->reg_lock);
@@ -270,13 +271,28 @@ static irqreturn_t mv88e6xxx_g1_irq_thread_work(struct mv88e6xxx_chip *chip)
        if (err)
                goto out;
 
-       for (n = 0; n < chip->g1_irq.nirqs; ++n) {
-               if (reg & (1 << n)) {
-                       sub_irq = irq_find_mapping(chip->g1_irq.domain, n);
-                       handle_nested_irq(sub_irq);
-                       ++nhandled;
+       do {
+               for (n = 0; n < chip->g1_irq.nirqs; ++n) {
+                       if (reg & (1 << n)) {
+                               sub_irq = irq_find_mapping(chip->g1_irq.domain,
+                                                          n);
+                               handle_nested_irq(sub_irq);
+                               ++nhandled;
+                       }
                }
-       }
+
+               mutex_lock(&chip->reg_lock);
+               err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_CTL1, &ctl1);
+               if (err)
+                       goto unlock;
+               err = mv88e6xxx_g1_read(chip, MV88E6XXX_G1_STS, &reg);
+unlock:
+               mutex_unlock(&chip->reg_lock);
+               if (err)
+                       goto out;
+               ctl1 &= GENMASK(chip->g1_irq.nirqs, 0);
+       } while (reg & ctl1);
+
 out:
        return (nhandled > 0 ? IRQ_HANDLED : IRQ_NONE);
 }
@@ -2403,6 +2419,107 @@ static int mv88e6xxx_stats_setup(struct mv88e6xxx_chip *chip)
        return mv88e6xxx_g1_stats_clear(chip);
 }
 
+/* The mv88e6390 has some hidden registers used for debug and
+ * development. The errata also makes use of them.
+ */
+static int mv88e6390_hidden_write(struct mv88e6xxx_chip *chip, int port,
+                                 int reg, u16 val)
+{
+       u16 ctrl;
+       int err;
+
+       err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_DATA_PORT,
+                                  PORT_RESERVED_1A, val);
+       if (err)
+               return err;
+
+       ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_WRITE |
+              PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
+              reg;
+
+       return mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
+                                   PORT_RESERVED_1A, ctrl);
+}
+
+static int mv88e6390_hidden_wait(struct mv88e6xxx_chip *chip)
+{
+       return mv88e6xxx_wait(chip, PORT_RESERVED_1A_CTRL_PORT,
+                             PORT_RESERVED_1A, PORT_RESERVED_1A_BUSY);
+}
+
+
+static int mv88e6390_hidden_read(struct mv88e6xxx_chip *chip, int port,
+                                 int reg, u16 *val)
+{
+       u16 ctrl;
+       int err;
+
+       ctrl = PORT_RESERVED_1A_BUSY | PORT_RESERVED_1A_READ |
+              PORT_RESERVED_1A_BLOCK | port << PORT_RESERVED_1A_PORT_SHIFT |
+              reg;
+
+       err = mv88e6xxx_port_write(chip, PORT_RESERVED_1A_CTRL_PORT,
+                                  PORT_RESERVED_1A, ctrl);
+       if (err)
+               return err;
+
+       err = mv88e6390_hidden_wait(chip);
+       if (err)
+               return err;
+
+       return  mv88e6xxx_port_read(chip, PORT_RESERVED_1A_DATA_PORT,
+                                   PORT_RESERVED_1A, val);
+}
+
+/* Check if the errata has already been applied. */
+static bool mv88e6390_setup_errata_applied(struct mv88e6xxx_chip *chip)
+{
+       int port;
+       int err;
+       u16 val;
+
+       for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+               err = mv88e6390_hidden_read(chip, port, 0, &val);
+               if (err) {
+                       dev_err(chip->dev,
+                               "Error reading hidden register: %d\n", err);
+                       return false;
+               }
+               if (val != 0x01c0)
+                       return false;
+       }
+
+       return true;
+}
+
+/* The 6390 copper ports have an errata which require poking magic
+ * values into undocumented hidden registers and then performing a
+ * software reset.
+ */
+static int mv88e6390_setup_errata(struct mv88e6xxx_chip *chip)
+{
+       int port;
+       int err;
+
+       if (mv88e6390_setup_errata_applied(chip))
+               return 0;
+
+       /* Set the ports into blocking mode */
+       for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+               err = mv88e6xxx_port_set_state(chip, port, BR_STATE_DISABLED);
+               if (err)
+                       return err;
+       }
+
+       for (port = 0; port < mv88e6xxx_num_ports(chip); port++) {
+               err = mv88e6390_hidden_write(chip, port, 0, 0x01c0);
+               if (err)
+                       return err;
+       }
+
+       return mv88e6xxx_software_reset(chip);
+}
+
 static int mv88e6xxx_setup(struct dsa_switch *ds)
 {
        struct mv88e6xxx_chip *chip = ds->priv;
@@ -2415,6 +2532,12 @@ static int mv88e6xxx_setup(struct dsa_switch *ds)
 
        mutex_lock(&chip->reg_lock);
 
+       if (chip->info->ops->setup_errata) {
+               err = chip->info->ops->setup_errata(chip);
+               if (err)
+                       goto unlock;
+       }
+
        /* Cache the cmode of each port. */
        for (i = 0; i < mv88e6xxx_num_ports(chip); i++) {
                if (chip->info->ops->port_get_cmode) {
@@ -3226,6 +3349,7 @@ static const struct mv88e6xxx_ops mv88e6185_ops = {
 
 static const struct mv88e6xxx_ops mv88e6190_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3269,6 +3393,7 @@ static const struct mv88e6xxx_ops mv88e6190_ops = {
 
 static const struct mv88e6xxx_ops mv88e6190x_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3312,6 +3437,7 @@ static const struct mv88e6xxx_ops mv88e6190x_ops = {
 
 static const struct mv88e6xxx_ops mv88e6191_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3404,6 +3530,7 @@ static const struct mv88e6xxx_ops mv88e6240_ops = {
 
 static const struct mv88e6xxx_ops mv88e6290_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3709,6 +3836,7 @@ static const struct mv88e6xxx_ops mv88e6352_ops = {
 
 static const struct mv88e6xxx_ops mv88e6390_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
@@ -3756,6 +3884,7 @@ static const struct mv88e6xxx_ops mv88e6390_ops = {
 
 static const struct mv88e6xxx_ops mv88e6390x_ops = {
        /* MV88E6XXX_FAMILY_6390 */
+       .setup_errata = mv88e6390_setup_errata,
        .irl_init_all = mv88e6390_g2_irl_init_all,
        .get_eeprom = mv88e6xxx_g2_get_eeprom8,
        .set_eeprom = mv88e6xxx_g2_set_eeprom8,
index f9ecb78..546651d 100644 (file)
@@ -300,6 +300,11 @@ struct mv88e6xxx_mdio_bus {
 };
 
 struct mv88e6xxx_ops {
+       /* Switch Setup Errata, called early in the switch setup to
+        * allow any errata actions to be performed
+        */
+       int (*setup_errata)(struct mv88e6xxx_chip *chip);
+
        int (*ieee_pri_map)(struct mv88e6xxx_chip *chip);
        int (*ip_pri_map)(struct mv88e6xxx_chip *chip);
 
index 5200e4b..ea24384 100644 (file)
@@ -314,6 +314,7 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
 {
        struct mv88e6xxx_chip *chip = dev_id;
        struct mv88e6xxx_atu_entry entry;
+       int spid;
        int err;
        u16 val;
 
@@ -336,6 +337,8 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
        if (err)
                goto out;
 
+       spid = entry.state;
+
        if (val & MV88E6XXX_G1_ATU_OP_AGE_OUT_VIOLATION) {
                dev_err_ratelimited(chip->dev,
                                    "ATU age out violation for %pM\n",
@@ -344,23 +347,23 @@ static irqreturn_t mv88e6xxx_g1_atu_prob_irq_thread_fn(int irq, void *dev_id)
 
        if (val & MV88E6XXX_G1_ATU_OP_MEMBER_VIOLATION) {
                dev_err_ratelimited(chip->dev,
-                                   "ATU member violation for %pM portvec %x\n",
-                                   entry.mac, entry.portvec);
-               chip->ports[entry.portvec].atu_member_violation++;
+                                   "ATU member violation for %pM portvec %x spid %d\n",
+                                   entry.mac, entry.portvec, spid);
+               chip->ports[spid].atu_member_violation++;
        }
 
        if (val & MV88E6XXX_G1_ATU_OP_MISS_VIOLATION) {
                dev_err_ratelimited(chip->dev,
-                                   "ATU miss violation for %pM portvec %x\n",
-                                   entry.mac, entry.portvec);
-               chip->ports[entry.portvec].atu_miss_violation++;
+                                   "ATU miss violation for %pM portvec %x spid %d\n",
+                                   entry.mac, entry.portvec, spid);
+               chip->ports[spid].atu_miss_violation++;
        }
 
        if (val & MV88E6XXX_G1_ATU_OP_FULL_VIOLATION) {
                dev_err_ratelimited(chip->dev,
-                                   "ATU full violation for %pM portvec %x\n",
-                                   entry.mac, entry.portvec);
-               chip->ports[entry.portvec].atu_full_violation++;
+                                   "ATU full violation for %pM portvec %x spid %d\n",
+                                   entry.mac, entry.portvec, spid);
+               chip->ports[spid].atu_full_violation++;
        }
        mutex_unlock(&chip->reg_lock);
 
index 0d81866..e583641 100644 (file)
 /* Offset 0x19: Port IEEE Priority Remapping Registers (4-7) */
 #define MV88E6095_PORT_IEEE_PRIO_REMAP_4567    0x19
 
+/* Offset 0x1a: Magic undocumented errata register */
+#define PORT_RESERVED_1A                       0x1a
+#define PORT_RESERVED_1A_BUSY                  BIT(15)
+#define PORT_RESERVED_1A_WRITE                 BIT(14)
+#define PORT_RESERVED_1A_READ                  0
+#define PORT_RESERVED_1A_PORT_SHIFT            5
+#define PORT_RESERVED_1A_BLOCK                 (0xf << 10)
+#define PORT_RESERVED_1A_CTRL_PORT             4
+#define PORT_RESERVED_1A_DATA_PORT             5
+
 int mv88e6xxx_port_read(struct mv88e6xxx_chip *chip, int port, int reg,
                        u16 *val);
 int mv88e6xxx_port_write(struct mv88e6xxx_chip *chip, int port, int reg,
index 2caa8c8..1bfc5ff 100644 (file)
@@ -664,7 +664,7 @@ int mv88e6390_serdes_irq_setup(struct mv88e6xxx_chip *chip, int port)
        if (port < 9)
                return 0;
 
-       return mv88e6390_serdes_irq_setup(chip, port);
+       return mv88e6390x_serdes_irq_setup(chip, port);
 }
 
 void mv88e6390x_serdes_irq_free(struct mv88e6xxx_chip *chip, int port)
index b4b839a..ad41ec6 100644 (file)
@@ -347,16 +347,17 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi)
        struct device_node *mdio_np;
        int ret;
 
-       mdio_np = of_find_compatible_node(smi->dev->of_node, NULL,
-                                         "realtek,smi-mdio");
+       mdio_np = of_get_compatible_child(smi->dev->of_node, "realtek,smi-mdio");
        if (!mdio_np) {
                dev_err(smi->dev, "no MDIO bus node\n");
                return -ENODEV;
        }
 
        smi->slave_mii_bus = devm_mdiobus_alloc(smi->dev);
-       if (!smi->slave_mii_bus)
-               return -ENOMEM;
+       if (!smi->slave_mii_bus) {
+               ret = -ENOMEM;
+               goto err_put_node;
+       }
        smi->slave_mii_bus->priv = smi;
        smi->slave_mii_bus->name = "SMI slave MII";
        smi->slave_mii_bus->read = realtek_smi_mdio_read;
@@ -371,10 +372,15 @@ int realtek_smi_setup_mdio(struct realtek_smi *smi)
        if (ret) {
                dev_err(smi->dev, "unable to register MDIO bus %s\n",
                        smi->slave_mii_bus->id);
-               of_node_put(mdio_np);
+               goto err_put_node;
        }
 
        return 0;
+
+err_put_node:
+       of_node_put(mdio_np);
+
+       return ret;
 }
 
 static int realtek_smi_probe(struct platform_device *pdev)
@@ -457,6 +463,8 @@ static int realtek_smi_remove(struct platform_device *pdev)
        struct realtek_smi *smi = dev_get_drvdata(&pdev->dev);
 
        dsa_unregister_switch(smi->ds);
+       if (smi->slave_mii_bus)
+               of_node_put(smi->slave_mii_bus->dev.of_node);
        gpiod_set_value(smi->reset, 1);
 
        return 0;
index 91fc64c..47e5984 100644 (file)
@@ -1433,18 +1433,18 @@ static int greth_of_probe(struct platform_device *ofdev)
        }
 
        /* Allocate TX descriptor ring in coherent memory */
-       greth->tx_bd_base = dma_zalloc_coherent(greth->dev, 1024,
-                                               &greth->tx_bd_base_phys,
-                                               GFP_KERNEL);
+       greth->tx_bd_base = dma_alloc_coherent(greth->dev, 1024,
+                                              &greth->tx_bd_base_phys,
+                                              GFP_KERNEL);
        if (!greth->tx_bd_base) {
                err = -ENOMEM;
                goto error3;
        }
 
        /* Allocate RX descriptor ring in coherent memory */
-       greth->rx_bd_base = dma_zalloc_coherent(greth->dev, 1024,
-                                               &greth->rx_bd_base_phys,
-                                               GFP_KERNEL);
+       greth->rx_bd_base = dma_alloc_coherent(greth->dev, 1024,
+                                              &greth->rx_bd_base_phys,
+                                              GFP_KERNEL);
        if (!greth->rx_bd_base) {
                err = -ENOMEM;
                goto error4;
index 0b60921..16477aa 100644 (file)
@@ -795,8 +795,8 @@ static int slic_init_stat_queue(struct slic_device *sdev)
        size = stq->len * sizeof(*descs) + DESC_ALIGN_MASK;
 
        for (i = 0; i < SLIC_NUM_STAT_DESC_ARRAYS; i++) {
-               descs = dma_zalloc_coherent(&sdev->pdev->dev, size, &paddr,
-                                           GFP_KERNEL);
+               descs = dma_alloc_coherent(&sdev->pdev->dev, size, &paddr,
+                                          GFP_KERNEL);
                if (!descs) {
                        netdev_err(sdev->netdev,
                                   "failed to allocate status descriptors\n");
@@ -1240,8 +1240,8 @@ static int slic_init_shmem(struct slic_device *sdev)
        struct slic_shmem_data *sm_data;
        dma_addr_t paddr;
 
-       sm_data = dma_zalloc_coherent(&sdev->pdev->dev, sizeof(*sm_data),
-                                     &paddr, GFP_KERNEL);
+       sm_data = dma_alloc_coherent(&sdev->pdev->dev, sizeof(*sm_data),
+                                    &paddr, GFP_KERNEL);
        if (!sm_data) {
                dev_err(&sdev->pdev->dev, "failed to allocate shared memory\n");
                return -ENOMEM;
@@ -1621,8 +1621,8 @@ static int slic_read_eeprom(struct slic_device *sdev)
        int err = 0;
        u8 *mac[2];
 
-       eeprom = dma_zalloc_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE,
-                                    &paddr, GFP_KERNEL);
+       eeprom = dma_alloc_coherent(&sdev->pdev->dev, SLIC_EEPROM_SIZE,
+                                   &paddr, GFP_KERNEL);
        if (!eeprom)
                return -ENOMEM;
 
index 4f11f98..1827ef1 100644 (file)
@@ -2059,7 +2059,7 @@ static inline void ace_tx_int(struct net_device *dev,
                if (skb) {
                        dev->stats.tx_packets++;
                        dev->stats.tx_bytes += skb->len;
-                       dev_kfree_skb_irq(skb);
+                       dev_consume_skb_irq(skb);
                        info->skb = NULL;
                }
 
index 0fb986b..0ae723f 100644 (file)
@@ -145,7 +145,8 @@ u32 msgdma_tx_completions(struct altera_tse_private *priv)
                        & 0xffff;
 
        if (inuse) { /* Tx FIFO is not empty */
-               ready = priv->tx_prod - priv->tx_cons - inuse - 1;
+               ready = max_t(int,
+                             priv->tx_prod - priv->tx_cons - inuse - 1, 0);
        } else {
                /* Check for buffered last packet */
                status = csrrd32(priv->tx_dma_csr, msgdma_csroffs(status));
index 02921d8..aa1d1f5 100644 (file)
@@ -714,8 +714,10 @@ static struct phy_device *connect_local_phy(struct net_device *dev)
 
                phydev = phy_connect(dev, phy_id_fmt, &altera_tse_adjust_link,
                                     priv->phy_iface);
-               if (IS_ERR(phydev))
+               if (IS_ERR(phydev)) {
                        netdev_err(dev, "Could not attach to PHY\n");
+                       phydev = NULL;
+               }
 
        } else {
                int ret;
index 420cede..b17d435 100644 (file)
@@ -111,8 +111,8 @@ static int ena_com_admin_init_sq(struct ena_com_admin_queue *queue)
        struct ena_com_admin_sq *sq = &queue->sq;
        u16 size = ADMIN_SQ_SIZE(queue->q_depth);
 
-       sq->entries = dma_zalloc_coherent(queue->q_dmadev, size, &sq->dma_addr,
-                                         GFP_KERNEL);
+       sq->entries = dma_alloc_coherent(queue->q_dmadev, size, &sq->dma_addr,
+                                        GFP_KERNEL);
 
        if (!sq->entries) {
                pr_err("memory allocation failed");
@@ -133,8 +133,8 @@ static int ena_com_admin_init_cq(struct ena_com_admin_queue *queue)
        struct ena_com_admin_cq *cq = &queue->cq;
        u16 size = ADMIN_CQ_SIZE(queue->q_depth);
 
-       cq->entries = dma_zalloc_coherent(queue->q_dmadev, size, &cq->dma_addr,
-                                         GFP_KERNEL);
+       cq->entries = dma_alloc_coherent(queue->q_dmadev, size, &cq->dma_addr,
+                                        GFP_KERNEL);
 
        if (!cq->entries) {
                pr_err("memory allocation failed");
@@ -156,8 +156,8 @@ static int ena_com_admin_init_aenq(struct ena_com_dev *dev,
 
        dev->aenq.q_depth = ENA_ASYNC_QUEUE_DEPTH;
        size = ADMIN_AENQ_SIZE(ENA_ASYNC_QUEUE_DEPTH);
-       aenq->entries = dma_zalloc_coherent(dev->dmadev, size, &aenq->dma_addr,
-                                           GFP_KERNEL);
+       aenq->entries = dma_alloc_coherent(dev->dmadev, size, &aenq->dma_addr,
+                                          GFP_KERNEL);
 
        if (!aenq->entries) {
                pr_err("memory allocation failed");
@@ -344,15 +344,15 @@ static int ena_com_init_io_sq(struct ena_com_dev *ena_dev,
                dev_node = dev_to_node(ena_dev->dmadev);
                set_dev_node(ena_dev->dmadev, ctx->numa_node);
                io_sq->desc_addr.virt_addr =
-                       dma_zalloc_coherent(ena_dev->dmadev, size,
-                                           &io_sq->desc_addr.phys_addr,
-                                           GFP_KERNEL);
+                       dma_alloc_coherent(ena_dev->dmadev, size,
+                                          &io_sq->desc_addr.phys_addr,
+                                          GFP_KERNEL);
                set_dev_node(ena_dev->dmadev, dev_node);
                if (!io_sq->desc_addr.virt_addr) {
                        io_sq->desc_addr.virt_addr =
-                               dma_zalloc_coherent(ena_dev->dmadev, size,
-                                                   &io_sq->desc_addr.phys_addr,
-                                                   GFP_KERNEL);
+                               dma_alloc_coherent(ena_dev->dmadev, size,
+                                                  &io_sq->desc_addr.phys_addr,
+                                                  GFP_KERNEL);
                }
 
                if (!io_sq->desc_addr.virt_addr) {
@@ -425,14 +425,14 @@ static int ena_com_init_io_cq(struct ena_com_dev *ena_dev,
        prev_node = dev_to_node(ena_dev->dmadev);
        set_dev_node(ena_dev->dmadev, ctx->numa_node);
        io_cq->cdesc_addr.virt_addr =
-               dma_zalloc_coherent(ena_dev->dmadev, size,
-                                   &io_cq->cdesc_addr.phys_addr, GFP_KERNEL);
+               dma_alloc_coherent(ena_dev->dmadev, size,
+                                  &io_cq->cdesc_addr.phys_addr, GFP_KERNEL);
        set_dev_node(ena_dev->dmadev, prev_node);
        if (!io_cq->cdesc_addr.virt_addr) {
                io_cq->cdesc_addr.virt_addr =
-                       dma_zalloc_coherent(ena_dev->dmadev, size,
-                                           &io_cq->cdesc_addr.phys_addr,
-                                           GFP_KERNEL);
+                       dma_alloc_coherent(ena_dev->dmadev, size,
+                                          &io_cq->cdesc_addr.phys_addr,
+                                          GFP_KERNEL);
        }
 
        if (!io_cq->cdesc_addr.virt_addr) {
@@ -1026,8 +1026,8 @@ static int ena_com_hash_key_allocate(struct ena_com_dev *ena_dev)
        struct ena_rss *rss = &ena_dev->rss;
 
        rss->hash_key =
-               dma_zalloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_key),
-                                   &rss->hash_key_dma_addr, GFP_KERNEL);
+               dma_alloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_key),
+                                  &rss->hash_key_dma_addr, GFP_KERNEL);
 
        if (unlikely(!rss->hash_key))
                return -ENOMEM;
@@ -1050,8 +1050,8 @@ static int ena_com_hash_ctrl_init(struct ena_com_dev *ena_dev)
        struct ena_rss *rss = &ena_dev->rss;
 
        rss->hash_ctrl =
-               dma_zalloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_ctrl),
-                                   &rss->hash_ctrl_dma_addr, GFP_KERNEL);
+               dma_alloc_coherent(ena_dev->dmadev, sizeof(*rss->hash_ctrl),
+                                  &rss->hash_ctrl_dma_addr, GFP_KERNEL);
 
        if (unlikely(!rss->hash_ctrl))
                return -ENOMEM;
@@ -1094,8 +1094,8 @@ static int ena_com_indirect_table_allocate(struct ena_com_dev *ena_dev,
                sizeof(struct ena_admin_rss_ind_table_entry);
 
        rss->rss_ind_tbl =
-               dma_zalloc_coherent(ena_dev->dmadev, tbl_size,
-                                   &rss->rss_ind_tbl_dma_addr, GFP_KERNEL);
+               dma_alloc_coherent(ena_dev->dmadev, tbl_size,
+                                  &rss->rss_ind_tbl_dma_addr, GFP_KERNEL);
        if (unlikely(!rss->rss_ind_tbl))
                goto mem_err1;
 
@@ -1649,9 +1649,9 @@ int ena_com_mmio_reg_read_request_init(struct ena_com_dev *ena_dev)
 
        spin_lock_init(&mmio_read->lock);
        mmio_read->read_resp =
-               dma_zalloc_coherent(ena_dev->dmadev,
-                                   sizeof(*mmio_read->read_resp),
-                                   &mmio_read->read_resp_dma_addr, GFP_KERNEL);
+               dma_alloc_coherent(ena_dev->dmadev,
+                                  sizeof(*mmio_read->read_resp),
+                                  &mmio_read->read_resp_dma_addr, GFP_KERNEL);
        if (unlikely(!mmio_read->read_resp))
                goto err;
 
@@ -2623,8 +2623,8 @@ int ena_com_allocate_host_info(struct ena_com_dev *ena_dev)
        struct ena_host_attribute *host_attr = &ena_dev->host_attr;
 
        host_attr->host_info =
-               dma_zalloc_coherent(ena_dev->dmadev, SZ_4K,
-                                   &host_attr->host_info_dma_addr, GFP_KERNEL);
+               dma_alloc_coherent(ena_dev->dmadev, SZ_4K,
+                                  &host_attr->host_info_dma_addr, GFP_KERNEL);
        if (unlikely(!host_attr->host_info))
                return -ENOMEM;
 
@@ -2641,8 +2641,9 @@ int ena_com_allocate_debug_area(struct ena_com_dev *ena_dev,
        struct ena_host_attribute *host_attr = &ena_dev->host_attr;
 
        host_attr->debug_area_virt_addr =
-               dma_zalloc_coherent(ena_dev->dmadev, debug_area_size,
-                                   &host_attr->debug_area_dma_addr, GFP_KERNEL);
+               dma_alloc_coherent(ena_dev->dmadev, debug_area_size,
+                                  &host_attr->debug_area_dma_addr,
+                                  GFP_KERNEL);
        if (unlikely(!host_attr->debug_area_virt_addr)) {
                host_attr->debug_area_size = 0;
                return -ENOMEM;
index a70bb1b..a6eacf2 100644 (file)
@@ -2663,11 +2663,6 @@ static int ena_restore_device(struct ena_adapter *adapter)
                goto err_device_destroy;
        }
 
-       clear_bit(ENA_FLAG_ONGOING_RESET, &adapter->flags);
-       /* Make sure we don't have a race with AENQ Links state handler */
-       if (test_bit(ENA_FLAG_LINK_UP, &adapter->flags))
-               netif_carrier_on(adapter->netdev);
-
        rc = ena_enable_msix_and_set_admin_interrupts(adapter,
                                                      adapter->num_queues);
        if (rc) {
@@ -2684,6 +2679,11 @@ static int ena_restore_device(struct ena_adapter *adapter)
        }
 
        set_bit(ENA_FLAG_DEVICE_RUNNING, &adapter->flags);
+
+       clear_bit(ENA_FLAG_ONGOING_RESET, &adapter->flags);
+       if (test_bit(ENA_FLAG_LINK_UP, &adapter->flags))
+               netif_carrier_on(adapter->netdev);
+
        mod_timer(&adapter->timer_service, round_jiffies(jiffies + HZ));
        dev_err(&pdev->dev,
                "Device reset completed successfully, Driver info: %s\n",
index dc8b617..6387007 100644 (file)
@@ -45,7 +45,7 @@
 
 #define DRV_MODULE_VER_MAJOR   2
 #define DRV_MODULE_VER_MINOR   0
-#define DRV_MODULE_VER_SUBMINOR 2
+#define DRV_MODULE_VER_SUBMINOR 3
 
 #define DRV_MODULE_NAME                "ena"
 #ifndef DRV_MODULE_VERSION
index a90080f..e548c0a 100644 (file)
@@ -666,7 +666,7 @@ static int amd8111e_tx(struct net_device *dev)
                        pci_unmap_single(lp->pci_dev, lp->tx_dma_addr[tx_index],
                                        lp->tx_skbuff[tx_index]->len,
                                        PCI_DMA_TODEVICE);
-                       dev_kfree_skb_irq (lp->tx_skbuff[tx_index]);
+                       dev_consume_skb_irq(lp->tx_skbuff[tx_index]);
                        lp->tx_skbuff[tx_index] = NULL;
                        lp->tx_dma_addr[tx_index] = 0;
                }
index d272dc6..b40d437 100644 (file)
 #define MAC_MDIOSCAR_PA_WIDTH          5
 #define MAC_MDIOSCAR_RA_INDEX          0
 #define MAC_MDIOSCAR_RA_WIDTH          16
-#define MAC_MDIOSCAR_REG_INDEX         0
-#define MAC_MDIOSCAR_REG_WIDTH         21
 #define MAC_MDIOSCCDR_BUSY_INDEX       22
 #define MAC_MDIOSCCDR_BUSY_WIDTH       1
 #define MAC_MDIOSCCDR_CMD_INDEX                16
index 1e929a1..4666084 100644 (file)
@@ -1284,6 +1284,20 @@ static void xgbe_write_mmd_regs(struct xgbe_prv_data *pdata, int prtad,
        }
 }
 
+static unsigned int xgbe_create_mdio_sca(int port, int reg)
+{
+       unsigned int mdio_sca, da;
+
+       da = (reg & MII_ADDR_C45) ? reg >> 16 : 0;
+
+       mdio_sca = 0;
+       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, RA, reg);
+       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, PA, port);
+       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, da);
+
+       return mdio_sca;
+}
+
 static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
                                   int reg, u16 val)
 {
@@ -1291,9 +1305,7 @@ static int xgbe_write_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
 
        reinit_completion(&pdata->mdio_complete);
 
-       mdio_sca = 0;
-       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
-       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
+       mdio_sca = xgbe_create_mdio_sca(addr, reg);
        XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
 
        mdio_sccd = 0;
@@ -1317,9 +1329,7 @@ static int xgbe_read_ext_mii_regs(struct xgbe_prv_data *pdata, int addr,
 
        reinit_completion(&pdata->mdio_complete);
 
-       mdio_sca = 0;
-       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, REG, reg);
-       XGMAC_SET_BITS(mdio_sca, MAC_MDIOSCAR, DA, addr);
+       mdio_sca = xgbe_create_mdio_sca(addr, reg);
        XGMAC_IOWRITE(pdata, MAC_MDIOSCAR, mdio_sca);
 
        mdio_sccd = 0;
index 0f2ad50..87b142a 100644 (file)
@@ -206,8 +206,8 @@ static netdev_tx_t xge_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        }
 
        /* Packet buffers should be 64B aligned */
-       pkt_buf = dma_zalloc_coherent(dev, XGENE_ENET_STD_MTU, &dma_addr,
-                                     GFP_ATOMIC);
+       pkt_buf = dma_alloc_coherent(dev, XGENE_ENET_STD_MTU, &dma_addr,
+                                    GFP_ATOMIC);
        if (unlikely(!pkt_buf)) {
                dev_kfree_skb_any(skb);
                return NETDEV_TX_OK;
@@ -428,8 +428,8 @@ static struct xge_desc_ring *xge_create_desc_ring(struct net_device *ndev)
        ring->ndev = ndev;
 
        size = XGENE_ENET_DESC_SIZE * XGENE_ENET_NUM_DESC;
-       ring->desc_addr = dma_zalloc_coherent(dev, size, &ring->dma_addr,
-                                             GFP_KERNEL);
+       ring->desc_addr = dma_alloc_coherent(dev, size, &ring->dma_addr,
+                                            GFP_KERNEL);
        if (!ring->desc_addr)
                goto err;
 
index 6a8e256..4d3855c 100644 (file)
@@ -777,7 +777,7 @@ static irqreturn_t bmac_txdma_intr(int irq, void *dev_id)
 
                if (bp->tx_bufs[bp->tx_empty]) {
                        ++dev->stats.tx_packets;
-                       dev_kfree_skb_irq(bp->tx_bufs[bp->tx_empty]);
+                       dev_consume_skb_irq(bp->tx_bufs[bp->tx_empty]);
                }
                bp->tx_bufs[bp->tx_empty] = NULL;
                bp->tx_fullup = 0;
index c131cfc..e3538ba 100644 (file)
@@ -660,10 +660,9 @@ static int alx_alloc_rings(struct alx_priv *alx)
                            alx->num_txq +
                            sizeof(struct alx_rrd) * alx->rx_ringsz +
                            sizeof(struct alx_rfd) * alx->rx_ringsz;
-       alx->descmem.virt = dma_zalloc_coherent(&alx->hw.pdev->dev,
-                                               alx->descmem.size,
-                                               &alx->descmem.dma,
-                                               GFP_KERNEL);
+       alx->descmem.virt = dma_alloc_coherent(&alx->hw.pdev->dev,
+                                              alx->descmem.size,
+                                              &alx->descmem.dma, GFP_KERNEL);
        if (!alx->descmem.virt)
                return -ENOMEM;
 
index 7087b88..3a3b35b 100644 (file)
@@ -1019,8 +1019,8 @@ static int atl1c_setup_ring_resources(struct atl1c_adapter *adapter)
                sizeof(struct atl1c_recv_ret_status) * rx_desc_count +
                8 * 4;
 
-       ring_header->desc = dma_zalloc_coherent(&pdev->dev, ring_header->size,
-                                               &ring_header->dma, GFP_KERNEL);
+       ring_header->desc = dma_alloc_coherent(&pdev->dev, ring_header->size,
+                                              &ring_header->dma, GFP_KERNEL);
        if (unlikely(!ring_header->desc)) {
                dev_err(&pdev->dev, "could not get memory for DMA buffer\n");
                goto err_nomem;
index bb41bec..31ff1e0 100644 (file)
@@ -1335,13 +1335,11 @@ static int atl2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct net_device *netdev;
        struct atl2_adapter *adapter;
-       static int cards_found;
+       static int cards_found = 0;
        unsigned long mmio_start;
        int mmio_len;
        int err;
 
-       cards_found = 0;
-
        err = pci_enable_device(pdev);
        if (err)
                return err;
index f448089..97ab0dd 100644 (file)
@@ -638,7 +638,7 @@ static void b44_tx(struct b44 *bp)
                bytes_compl += skb->len;
                pkts_compl++;
 
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
        }
 
        netdev_completed_queue(bp->dev, pkts_compl, bytes_compl);
@@ -1012,7 +1012,7 @@ static netdev_tx_t b44_start_xmit(struct sk_buff *skb, struct net_device *dev)
                }
 
                skb_copy_from_linear_data(skb, skb_put(bounce_skb, len), len);
-               dev_kfree_skb_any(skb);
+               dev_consume_skb_any(skb);
                skb = bounce_skb;
        }
 
index 6bae973..09cd188 100644 (file)
@@ -936,7 +936,7 @@ static int bcm_enet_open(struct net_device *dev)
 
        /* allocate rx dma ring */
        size = priv->rx_ring_size * sizeof(struct bcm_enet_desc);
-       p = dma_zalloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
+       p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
        if (!p) {
                ret = -ENOMEM;
                goto out_freeirq_tx;
@@ -947,7 +947,7 @@ static int bcm_enet_open(struct net_device *dev)
 
        /* allocate tx dma ring */
        size = priv->tx_ring_size * sizeof(struct bcm_enet_desc);
-       p = dma_zalloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
+       p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
        if (!p) {
                ret = -ENOMEM;
                goto out_free_rx_ring;
@@ -2120,7 +2120,7 @@ static int bcm_enetsw_open(struct net_device *dev)
 
        /* allocate rx dma ring */
        size = priv->rx_ring_size * sizeof(struct bcm_enet_desc);
-       p = dma_zalloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
+       p = dma_alloc_coherent(kdev, size, &priv->rx_desc_dma, GFP_KERNEL);
        if (!p) {
                dev_err(kdev, "cannot allocate rx ring %u\n", size);
                ret = -ENOMEM;
@@ -2132,7 +2132,7 @@ static int bcm_enetsw_open(struct net_device *dev)
 
        /* allocate tx dma ring */
        size = priv->tx_ring_size * sizeof(struct bcm_enet_desc);
-       p = dma_zalloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
+       p = dma_alloc_coherent(kdev, size, &priv->tx_desc_dma, GFP_KERNEL);
        if (!p) {
                dev_err(kdev, "cannot allocate tx ring\n");
                ret = -ENOMEM;
index 4574275..bc3ac36 100644 (file)
@@ -134,6 +134,10 @@ static void bcm_sysport_set_rx_csum(struct net_device *dev,
 
        priv->rx_chk_en = !!(wanted & NETIF_F_RXCSUM);
        reg = rxchk_readl(priv, RXCHK_CONTROL);
+       /* Clear L2 header checks, which would prevent BPDUs
+        * from being received.
+        */
+       reg &= ~RXCHK_L2_HDR_DIS;
        if (priv->rx_chk_en)
                reg |= RXCHK_EN;
        else
@@ -520,7 +524,6 @@ static void bcm_sysport_get_wol(struct net_device *dev,
                                struct ethtool_wolinfo *wol)
 {
        struct bcm_sysport_priv *priv = netdev_priv(dev);
-       u32 reg;
 
        wol->supported = WAKE_MAGIC | WAKE_MAGICSECURE | WAKE_FILTER;
        wol->wolopts = priv->wolopts;
@@ -528,11 +531,7 @@ static void bcm_sysport_get_wol(struct net_device *dev,
        if (!(priv->wolopts & WAKE_MAGICSECURE))
                return;
 
-       /* Return the programmed SecureOn password */
-       reg = umac_readl(priv, UMAC_PSW_MS);
-       put_unaligned_be16(reg, &wol->sopass[0]);
-       reg = umac_readl(priv, UMAC_PSW_LS);
-       put_unaligned_be32(reg, &wol->sopass[2]);
+       memcpy(wol->sopass, priv->sopass, sizeof(priv->sopass));
 }
 
 static int bcm_sysport_set_wol(struct net_device *dev,
@@ -548,13 +547,8 @@ static int bcm_sysport_set_wol(struct net_device *dev,
        if (wol->wolopts & ~supported)
                return -EINVAL;
 
-       /* Program the SecureOn password */
-       if (wol->wolopts & WAKE_MAGICSECURE) {
-               umac_writel(priv, get_unaligned_be16(&wol->sopass[0]),
-                           UMAC_PSW_MS);
-               umac_writel(priv, get_unaligned_be32(&wol->sopass[2]),
-                           UMAC_PSW_LS);
-       }
+       if (wol->wolopts & WAKE_MAGICSECURE)
+               memcpy(priv->sopass, wol->sopass, sizeof(priv->sopass));
 
        /* Flag the device and relevant IRQ as wakeup capable */
        if (wol->wolopts) {
@@ -1506,8 +1500,8 @@ static int bcm_sysport_init_tx_ring(struct bcm_sysport_priv *priv,
        /* We just need one DMA descriptor which is DMA-able, since writing to
         * the port will allocate a new descriptor in its internal linked-list
         */
-       p = dma_zalloc_coherent(kdev, sizeof(struct dma_desc), &ring->desc_dma,
-                               GFP_KERNEL);
+       p = dma_alloc_coherent(kdev, sizeof(struct dma_desc), &ring->desc_dma,
+                              GFP_KERNEL);
        if (!p) {
                netif_err(priv, hw, priv->netdev, "DMA alloc failed\n");
                return -ENOMEM;
@@ -2649,13 +2643,18 @@ static int bcm_sysport_suspend_to_wol(struct bcm_sysport_priv *priv)
        unsigned int index, i = 0;
        u32 reg;
 
-       /* Password has already been programmed */
        reg = umac_readl(priv, UMAC_MPD_CTRL);
        if (priv->wolopts & (WAKE_MAGIC | WAKE_MAGICSECURE))
                reg |= MPD_EN;
        reg &= ~PSW_EN;
-       if (priv->wolopts & WAKE_MAGICSECURE)
+       if (priv->wolopts & WAKE_MAGICSECURE) {
+               /* Program the SecureOn password */
+               umac_writel(priv, get_unaligned_be16(&priv->sopass[0]),
+                           UMAC_PSW_MS);
+               umac_writel(priv, get_unaligned_be32(&priv->sopass[2]),
+                           UMAC_PSW_LS);
                reg |= PSW_EN;
+       }
        umac_writel(priv, reg, UMAC_MPD_CTRL);
 
        if (priv->wolopts & WAKE_FILTER) {
index 0887e63..0b192fe 100644 (file)
@@ -12,6 +12,7 @@
 #define __BCM_SYSPORT_H
 
 #include <linux/bitmap.h>
+#include <linux/ethtool.h>
 #include <linux/if_vlan.h>
 #include <linux/net_dim.h>
 
@@ -778,6 +779,7 @@ struct bcm_sysport_priv {
        unsigned int            crc_fwd:1;
        u16                     rev;
        u32                     wolopts;
+       u8                      sopass[SOPASS_MAX];
        unsigned int            wol_irq_disabled:1;
 
        /* MIB related fields */
index cabc8e4..2d3a44c 100644 (file)
@@ -634,9 +634,9 @@ static int bgmac_dma_alloc(struct bgmac *bgmac)
 
                /* Alloc ring of descriptors */
                size = BGMAC_TX_RING_SLOTS * sizeof(struct bgmac_dma_desc);
-               ring->cpu_base = dma_zalloc_coherent(dma_dev, size,
-                                                    &ring->dma_base,
-                                                    GFP_KERNEL);
+               ring->cpu_base = dma_alloc_coherent(dma_dev, size,
+                                                   &ring->dma_base,
+                                                   GFP_KERNEL);
                if (!ring->cpu_base) {
                        dev_err(bgmac->dev, "Allocation of TX ring 0x%X failed\n",
                                ring->mmio_base);
@@ -659,9 +659,9 @@ static int bgmac_dma_alloc(struct bgmac *bgmac)
 
                /* Alloc ring of descriptors */
                size = BGMAC_RX_RING_SLOTS * sizeof(struct bgmac_dma_desc);
-               ring->cpu_base = dma_zalloc_coherent(dma_dev, size,
-                                                    &ring->dma_base,
-                                                    GFP_KERNEL);
+               ring->cpu_base = dma_alloc_coherent(dma_dev, size,
+                                                   &ring->dma_base,
+                                                   GFP_KERNEL);
                if (!ring->cpu_base) {
                        dev_err(bgmac->dev, "Allocation of RX ring 0x%X failed\n",
                                ring->mmio_base);
index bbb2471..d63371d 100644 (file)
@@ -844,8 +844,8 @@ bnx2_alloc_stats_blk(struct net_device *dev)
                                                 BNX2_SBLK_MSIX_ALIGN_SIZE);
        bp->status_stats_size = status_blk_size +
                                sizeof(struct statistics_block);
-       status_blk = dma_zalloc_coherent(&bp->pdev->dev, bp->status_stats_size,
-                                        &bp->status_blk_mapping, GFP_KERNEL);
+       status_blk = dma_alloc_coherent(&bp->pdev->dev, bp->status_stats_size,
+                                       &bp->status_blk_mapping, GFP_KERNEL);
        if (!status_blk)
                return -ENOMEM;
 
index 5cd3135..03d131f 100644 (file)
@@ -2081,7 +2081,7 @@ void bnx2x_igu_clear_sb_gen(struct bnx2x *bp, u8 func, u8 idu_sb_id,
                            bool is_pf);
 
 #define BNX2X_ILT_ZALLOC(x, y, size)                                   \
-       x = dma_zalloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL)
+       x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL)
 
 #define BNX2X_ILT_FREE(x, y, size) \
        do { \
index 142bc11..2462e7a 100644 (file)
@@ -52,7 +52,7 @@ extern int bnx2x_num_queues;
 
 #define BNX2X_PCI_ALLOC(y, size)                                       \
 ({                                                                     \
-       void *x = dma_zalloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
+       void *x = dma_alloc_coherent(&bp->pdev->dev, size, y, GFP_KERNEL); \
        if (x)                                                          \
                DP(NETIF_MSG_HW,                                        \
                   "BNX2X_PCI_ALLOC: Physical %Lx Virtual %p\n",        \
index 3aa80da..d95730c 100644 (file)
@@ -3449,10 +3449,10 @@ alloc_ext_stats:
                        goto alloc_tx_ext_stats;
 
                bp->hw_rx_port_stats_ext =
-                       dma_zalloc_coherent(&pdev->dev,
-                                           sizeof(struct rx_port_stats_ext),
-                                           &bp->hw_rx_port_stats_ext_map,
-                                           GFP_KERNEL);
+                       dma_alloc_coherent(&pdev->dev,
+                                          sizeof(struct rx_port_stats_ext),
+                                          &bp->hw_rx_port_stats_ext_map,
+                                          GFP_KERNEL);
                if (!bp->hw_rx_port_stats_ext)
                        return 0;
 
@@ -3462,10 +3462,10 @@ alloc_tx_ext_stats:
 
                if (bp->hwrm_spec_code >= 0x10902) {
                        bp->hw_tx_port_stats_ext =
-                               dma_zalloc_coherent(&pdev->dev,
-                                           sizeof(struct tx_port_stats_ext),
-                                           &bp->hw_tx_port_stats_ext_map,
-                                           GFP_KERNEL);
+                               dma_alloc_coherent(&pdev->dev,
+                                                  sizeof(struct tx_port_stats_ext),
+                                                  &bp->hw_tx_port_stats_ext_map,
+                                                  GFP_KERNEL);
                }
                bp->flags |= BNXT_FLAG_PORT_STATS_EXT;
        }
@@ -3903,7 +3903,7 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
                        if (len)
                                break;
                        /* on first few passes, just barely sleep */
-                       if (i < DFLT_HWRM_CMD_TIMEOUT)
+                       if (i < HWRM_SHORT_TIMEOUT_COUNTER)
                                usleep_range(HWRM_SHORT_MIN_TIMEOUT,
                                             HWRM_SHORT_MAX_TIMEOUT);
                        else
@@ -3926,7 +3926,7 @@ static int bnxt_hwrm_do_send_msg(struct bnxt *bp, void *msg, u32 msg_len,
                        dma_rmb();
                        if (*valid)
                                break;
-                       udelay(1);
+                       usleep_range(1, 5);
                }
 
                if (j >= HWRM_VALID_BIT_DELAY_USEC) {
@@ -4973,12 +4973,18 @@ static int bnxt_hwrm_ring_alloc(struct bnxt *bp)
                struct bnxt_cp_ring_info *cpr = &bnapi->cp_ring;
                struct bnxt_ring_struct *ring = &cpr->cp_ring_struct;
                u32 map_idx = ring->map_idx;
+               unsigned int vector;
 
+               vector = bp->irq_tbl[map_idx].vector;
+               disable_irq_nosync(vector);
                rc = hwrm_ring_alloc_send_msg(bp, ring, type, map_idx);
-               if (rc)
+               if (rc) {
+                       enable_irq(vector);
                        goto err_out;
+               }
                bnxt_set_db(bp, &cpr->cp_db, type, map_idx, ring->fw_ring_id);
                bnxt_db_nq(bp, &cpr->cp_db, cpr->cp_raw_cons);
+               enable_irq(vector);
                bp->grp_info[i].cp_fw_ring_id = ring->fw_ring_id;
 
                if (!i) {
@@ -5601,7 +5607,8 @@ static int bnxt_hwrm_check_pf_rings(struct bnxt *bp, int tx_rings, int rx_rings,
                         FUNC_CFG_REQ_FLAGS_STAT_CTX_ASSETS_TEST |
                         FUNC_CFG_REQ_FLAGS_VNIC_ASSETS_TEST;
                if (bp->flags & BNXT_FLAG_CHIP_P5)
-                       flags |= FUNC_CFG_REQ_FLAGS_RSSCOS_CTX_ASSETS_TEST;
+                       flags |= FUNC_CFG_REQ_FLAGS_RSSCOS_CTX_ASSETS_TEST |
+                                FUNC_CFG_REQ_FLAGS_NQ_ASSETS_TEST;
                else
                        flags |= FUNC_CFG_REQ_FLAGS_RING_GRP_ASSETS_TEST;
        }
@@ -6221,9 +6228,12 @@ static int bnxt_alloc_ctx_pg_tbls(struct bnxt *bp,
                        rmem->pg_tbl_map = ctx_pg->ctx_dma_arr[i];
                        rmem->depth = 1;
                        rmem->nr_pages = MAX_CTX_PAGES;
-                       if (i == (nr_tbls - 1))
-                               rmem->nr_pages = ctx_pg->nr_pages %
-                                                MAX_CTX_PAGES;
+                       if (i == (nr_tbls - 1)) {
+                               int rem = ctx_pg->nr_pages % MAX_CTX_PAGES;
+
+                               if (rem)
+                                       rmem->nr_pages = rem;
+                       }
                        rc = bnxt_alloc_ctx_mem_blk(bp, pg_tbl);
                        if (rc)
                                break;
index a451796..2fb653e 100644 (file)
@@ -582,7 +582,7 @@ struct nqe_cn {
        (HWRM_SHORT_TIMEOUT_COUNTER * HWRM_SHORT_MIN_TIMEOUT +          \
         ((n) - HWRM_SHORT_TIMEOUT_COUNTER) * HWRM_MIN_TIMEOUT))
 
-#define HWRM_VALID_BIT_DELAY_USEC      20
+#define HWRM_VALID_BIT_DELAY_USEC      150
 
 #define BNXT_HWRM_CHNL_CHIMP   0
 #define BNXT_HWRM_CHNL_KONG    1
index 15c7041..7077515 100644 (file)
@@ -316,8 +316,8 @@ static int bnxt_hwrm_set_dcbx_app(struct bnxt *bp, struct dcb_app *app,
 
        n = IEEE_8021QAZ_MAX_TCS;
        data_len = sizeof(*data) + sizeof(*fw_app) * n;
-       data = dma_zalloc_coherent(&bp->pdev->dev, data_len, &mapping,
-                                  GFP_KERNEL);
+       data = dma_alloc_coherent(&bp->pdev->dev, data_len, &mapping,
+                                 GFP_KERNEL);
        if (!data)
                return -ENOMEM;
 
index 140dbd6..7f56032 100644 (file)
@@ -85,8 +85,8 @@ static int bnxt_hwrm_nvm_req(struct bnxt *bp, u32 param_id, void *msg,
                return -EFAULT;
        }
 
-       data_addr = dma_zalloc_coherent(&bp->pdev->dev, bytesize,
-                                       &data_dma_addr, GFP_KERNEL);
+       data_addr = dma_alloc_coherent(&bp->pdev->dev, bytesize,
+                                      &data_dma_addr, GFP_KERNEL);
        if (!data_addr)
                return -ENOMEM;
 
index f1aaac8..0a09958 100644 (file)
@@ -386,8 +386,8 @@ struct hwrm_err_output {
 #define HWRM_VERSION_MAJOR 1
 #define HWRM_VERSION_MINOR 10
 #define HWRM_VERSION_UPDATE 0
-#define HWRM_VERSION_RSVD 33
-#define HWRM_VERSION_STR "1.10.0.33"
+#define HWRM_VERSION_RSVD 35
+#define HWRM_VERSION_STR "1.10.0.35"
 
 /* hwrm_ver_get_input (size:192b/24B) */
 struct hwrm_ver_get_input {
@@ -1184,6 +1184,7 @@ struct hwrm_func_cfg_input {
        #define FUNC_CFG_REQ_FLAGS_L2_CTX_ASSETS_TEST             0x100000UL
        #define FUNC_CFG_REQ_FLAGS_TRUSTED_VF_ENABLE              0x200000UL
        #define FUNC_CFG_REQ_FLAGS_DYNAMIC_TX_RING_ALLOC          0x400000UL
+       #define FUNC_CFG_REQ_FLAGS_NQ_ASSETS_TEST                 0x800000UL
        __le32  enables;
        #define FUNC_CFG_REQ_ENABLES_MTU                     0x1UL
        #define FUNC_CFG_REQ_ENABLES_MRU                     0x2UL
index 5db9f41..134ae28 100644 (file)
@@ -1288,7 +1288,7 @@ static void sbdma_tx_process(struct sbmac_softc *sc, struct sbmacdma *d,
                 * for transmits, we just free buffers.
                 */
 
-               dev_kfree_skb_irq(sb);
+               dev_consume_skb_irq(sb);
 
                /*
                 * .. and advance to the next buffer.
index 3b1397a..b1627dd 100644 (file)
@@ -8712,10 +8712,10 @@ static int tg3_mem_rx_acquire(struct tg3 *tp)
                if (!i && tg3_flag(tp, ENABLE_RSS))
                        continue;
 
-               tnapi->rx_rcb = dma_zalloc_coherent(&tp->pdev->dev,
-                                                   TG3_RX_RCB_RING_BYTES(tp),
-                                                   &tnapi->rx_rcb_mapping,
-                                                   GFP_KERNEL);
+               tnapi->rx_rcb = dma_alloc_coherent(&tp->pdev->dev,
+                                                  TG3_RX_RCB_RING_BYTES(tp),
+                                                  &tnapi->rx_rcb_mapping,
+                                                  GFP_KERNEL);
                if (!tnapi->rx_rcb)
                        goto err_out;
        }
@@ -8768,9 +8768,9 @@ static int tg3_alloc_consistent(struct tg3 *tp)
 {
        int i;
 
-       tp->hw_stats = dma_zalloc_coherent(&tp->pdev->dev,
-                                          sizeof(struct tg3_hw_stats),
-                                          &tp->stats_mapping, GFP_KERNEL);
+       tp->hw_stats = dma_alloc_coherent(&tp->pdev->dev,
+                                         sizeof(struct tg3_hw_stats),
+                                         &tp->stats_mapping, GFP_KERNEL);
        if (!tp->hw_stats)
                goto err_out;
 
@@ -8778,10 +8778,10 @@ static int tg3_alloc_consistent(struct tg3 *tp)
                struct tg3_napi *tnapi = &tp->napi[i];
                struct tg3_hw_status *sblk;
 
-               tnapi->hw_status = dma_zalloc_coherent(&tp->pdev->dev,
-                                                      TG3_HW_STATUS_SIZE,
-                                                      &tnapi->status_mapping,
-                                                      GFP_KERNEL);
+               tnapi->hw_status = dma_alloc_coherent(&tp->pdev->dev,
+                                                     TG3_HW_STATUS_SIZE,
+                                                     &tnapi->status_mapping,
+                                                     GFP_KERNEL);
                if (!tnapi->hw_status)
                        goto err_out;
 
index 3d45f4c..9bbaad9 100644 (file)
 #define MACB_CAPS_JUMBO                                0x00000020
 #define MACB_CAPS_GEM_HAS_PTP                  0x00000040
 #define MACB_CAPS_BD_RD_PREFETCH               0x00000080
+#define MACB_CAPS_NEEDS_RSTONUBR               0x00000100
 #define MACB_CAPS_FIFO_MODE                    0x10000000
 #define MACB_CAPS_GIGABIT_MODE_AVAILABLE       0x20000000
 #define MACB_CAPS_SG_DISABLED                  0x40000000
@@ -1214,6 +1215,8 @@ struct macb {
 
        int     rx_bd_rd_prefetch;
        int     tx_bd_rd_prefetch;
+
+       u32     rx_intr_mask;
 };
 
 #ifdef CONFIG_MACB_USE_HWSTAMP
index b126926..2b28826 100644 (file)
@@ -56,8 +56,7 @@
 /* level of occupied TX descriptors under which we wake up TX process */
 #define MACB_TX_WAKEUP_THRESH(bp)      (3 * (bp)->tx_ring_size / 4)
 
-#define MACB_RX_INT_FLAGS      (MACB_BIT(RCOMP) | MACB_BIT(RXUBR)      \
-                                | MACB_BIT(ISR_ROVR))
+#define MACB_RX_INT_FLAGS      (MACB_BIT(RCOMP) | MACB_BIT(ISR_ROVR))
 #define MACB_TX_ERR_FLAGS      (MACB_BIT(ISR_TUND)                     \
                                        | MACB_BIT(ISR_RLE)             \
                                        | MACB_BIT(TXERR))
@@ -1270,7 +1269,7 @@ static int macb_poll(struct napi_struct *napi, int budget)
                                queue_writel(queue, ISR, MACB_BIT(RCOMP));
                        napi_reschedule(napi);
                } else {
-                       queue_writel(queue, IER, MACB_RX_INT_FLAGS);
+                       queue_writel(queue, IER, bp->rx_intr_mask);
                }
        }
 
@@ -1288,7 +1287,7 @@ static void macb_hresp_error_task(unsigned long data)
        u32 ctrl;
 
        for (q = 0, queue = bp->queues; q < bp->num_queues; ++q, ++queue) {
-               queue_writel(queue, IDR, MACB_RX_INT_FLAGS |
+               queue_writel(queue, IDR, bp->rx_intr_mask |
                                         MACB_TX_INT_FLAGS |
                                         MACB_BIT(HRESP));
        }
@@ -1318,7 +1317,7 @@ static void macb_hresp_error_task(unsigned long data)
 
                /* Enable interrupts */
                queue_writel(queue, IER,
-                            MACB_RX_INT_FLAGS |
+                            bp->rx_intr_mask |
                             MACB_TX_INT_FLAGS |
                             MACB_BIT(HRESP));
        }
@@ -1372,14 +1371,14 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
                            (unsigned int)(queue - bp->queues),
                            (unsigned long)status);
 
-               if (status & MACB_RX_INT_FLAGS) {
+               if (status & bp->rx_intr_mask) {
                        /* There's no point taking any more interrupts
                         * until we have processed the buffers. The
                         * scheduling call may fail if the poll routine
                         * is already scheduled, so disable interrupts
                         * now.
                         */
-                       queue_writel(queue, IDR, MACB_RX_INT_FLAGS);
+                       queue_writel(queue, IDR, bp->rx_intr_mask);
                        if (bp->caps & MACB_CAPS_ISR_CLEAR_ON_WRITE)
                                queue_writel(queue, ISR, MACB_BIT(RCOMP));
 
@@ -1412,8 +1411,9 @@ static irqreturn_t macb_interrupt(int irq, void *dev_id)
                /* There is a hardware issue under heavy load where DMA can
                 * stop, this causes endless "used buffer descriptor read"
                 * interrupts but it can be cleared by re-enabling RX. See
-                * the at91 manual, section 41.3.1 or the Zynq manual
-                * section 16.7.4 for details.
+                * the at91rm9200 manual, section 41.3.1 or the Zynq manual
+                * section 16.7.4 for details. RXUBR is only enabled for
+                * these two versions.
                 */
                if (status & MACB_BIT(RXUBR)) {
                        ctrl = macb_readl(bp, NCR);
@@ -1738,12 +1738,8 @@ static int macb_pad_and_fcs(struct sk_buff **skb, struct net_device *ndev)
                *skb = nskb;
        }
 
-       if (padlen) {
-               if (padlen >= ETH_FCS_LEN)
-                       skb_put_zero(*skb, padlen - ETH_FCS_LEN);
-               else
-                       skb_trim(*skb, ETH_FCS_LEN - padlen);
-       }
+       if (padlen > ETH_FCS_LEN)
+               skb_put_zero(*skb, padlen - ETH_FCS_LEN);
 
 add_fcs:
        /* set FCS to packet */
@@ -2263,7 +2259,7 @@ static void macb_init_hw(struct macb *bp)
 
                /* Enable interrupts */
                queue_writel(queue, IER,
-                            MACB_RX_INT_FLAGS |
+                            bp->rx_intr_mask |
                             MACB_TX_INT_FLAGS |
                             MACB_BIT(HRESP));
        }
@@ -3911,6 +3907,7 @@ static const struct macb_config sama5d4_config = {
 };
 
 static const struct macb_config emac_config = {
+       .caps = MACB_CAPS_NEEDS_RSTONUBR,
        .clk_init = at91ether_clk_init,
        .init = at91ether_init,
 };
@@ -3932,7 +3929,8 @@ static const struct macb_config zynqmp_config = {
 };
 
 static const struct macb_config zynq_config = {
-       .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_NO_GIGABIT_HALF,
+       .caps = MACB_CAPS_GIGABIT_MODE_AVAILABLE | MACB_CAPS_NO_GIGABIT_HALF |
+               MACB_CAPS_NEEDS_RSTONUBR,
        .dma_burst_length = 16,
        .clk_init = macb_clk_init,
        .init = macb_init,
@@ -4087,6 +4085,10 @@ static int macb_probe(struct platform_device *pdev)
                                                macb_dma_desc_get_size(bp);
        }
 
+       bp->rx_intr_mask = MACB_RX_INT_FLAGS;
+       if (bp->caps & MACB_CAPS_NEEDS_RSTONUBR)
+               bp->rx_intr_mask |= MACB_BIT(RXUBR);
+
        mac = of_get_mac_address(np);
        if (mac) {
                ether_addr_copy(bp->dev->dev_addr, mac);
index 5f03199..05f4a3b 100644 (file)
@@ -54,7 +54,6 @@ config CAVIUM_PTP
        tristate "Cavium PTP coprocessor as PTP clock"
        depends on 64BIT && PCI
        imply PTP_1588_CLOCK
-       default y
        ---help---
          This driver adds support for the Precision Time Protocol Clocks and
          Timestamping coprocessor (PTP) found on Cavium processors.
index f4d8176..62636c1 100644 (file)
@@ -271,7 +271,7 @@ struct xcast_addr_list {
 };
 
 struct nicvf_work {
-       struct delayed_work    work;
+       struct work_struct     work;
        u8                     mode;
        struct xcast_addr_list *mc;
 };
@@ -327,7 +327,11 @@ struct nicvf {
        struct nicvf_work       rx_mode_work;
        /* spinlock to protect workqueue arguments from concurrent access */
        spinlock_t              rx_mode_wq_lock;
-
+       /* workqueue for handling kernel ndo_set_rx_mode() calls */
+       struct workqueue_struct *nicvf_rx_mode_wq;
+       /* mutex to protect VF's mailbox contents from concurrent access */
+       struct mutex            rx_mode_mtx;
+       struct delayed_work     link_change_work;
        /* PTP timestamp */
        struct cavium_ptp       *ptp_clock;
        /* Inbound timestamping is on */
@@ -575,10 +579,8 @@ struct set_ptp {
 
 struct xcast {
        u8    msg;
-       union {
-               u8    mode;
-               u64   mac;
-       } data;
+       u8    mode;
+       u64   mac:48;
 };
 
 /* 128 bit shared memory between PF and each VF */
index 6c8dcb6..c902528 100644 (file)
@@ -57,14 +57,8 @@ struct nicpf {
 #define        NIC_GET_BGX_FROM_VF_LMAC_MAP(map)       ((map >> 4) & 0xF)
 #define        NIC_GET_LMAC_FROM_VF_LMAC_MAP(map)      (map & 0xF)
        u8                      *vf_lmac_map;
-       struct delayed_work     dwork;
-       struct workqueue_struct *check_link;
-       u8                      *link;
-       u8                      *duplex;
-       u32                     *speed;
        u16                     cpi_base[MAX_NUM_VFS_SUPPORTED];
        u16                     rssi_base[MAX_NUM_VFS_SUPPORTED];
-       bool                    mbx_lock[MAX_NUM_VFS_SUPPORTED];
 
        /* MSI-X */
        u8                      num_vec;
@@ -929,6 +923,35 @@ static void nic_config_timestamp(struct nicpf *nic, int vf, struct set_ptp *ptp)
        nic_reg_write(nic, NIC_PF_PKIND_0_15_CFG | (pkind_idx << 3), pkind_val);
 }
 
+/* Get BGX LMAC link status and update corresponding VF
+ * if there is a change, valid only if internal L2 switch
+ * is not present otherwise VF link is always treated as up
+ */
+static void nic_link_status_get(struct nicpf *nic, u8 vf)
+{
+       union nic_mbx mbx = {};
+       struct bgx_link_status link;
+       u8 bgx, lmac;
+
+       mbx.link_status.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE;
+
+       /* Get BGX, LMAC indices for the VF */
+       bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+       lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
+
+       /* Get interface link status */
+       bgx_get_lmac_link_state(nic->node, bgx, lmac, &link);
+
+       /* Send a mbox message to VF with current link status */
+       mbx.link_status.link_up = link.link_up;
+       mbx.link_status.duplex = link.duplex;
+       mbx.link_status.speed = link.speed;
+       mbx.link_status.mac_type = link.mac_type;
+
+       /* reply with link status */
+       nic_send_msg_to_vf(nic, vf, &mbx);
+}
+
 /* Interrupt handler to handle mailbox messages from VFs */
 static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
 {
@@ -941,8 +964,6 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
        int i;
        int ret = 0;
 
-       nic->mbx_lock[vf] = true;
-
        mbx_addr = nic_get_mbx_addr(vf);
        mbx_data = (u64 *)&mbx;
 
@@ -957,12 +978,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
        switch (mbx.msg.msg) {
        case NIC_MBOX_MSG_READY:
                nic_mbx_send_ready(nic, vf);
-               if (vf < nic->num_vf_en) {
-                       nic->link[vf] = 0;
-                       nic->duplex[vf] = 0;
-                       nic->speed[vf] = 0;
-               }
-               goto unlock;
+               return;
        case NIC_MBOX_MSG_QS_CFG:
                reg_addr = NIC_PF_QSET_0_127_CFG |
                           (mbx.qs.num << NIC_QS_ID_SHIFT);
@@ -1031,7 +1047,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
                break;
        case NIC_MBOX_MSG_RSS_SIZE:
                nic_send_rss_size(nic, vf);
-               goto unlock;
+               return;
        case NIC_MBOX_MSG_RSS_CFG:
        case NIC_MBOX_MSG_RSS_CFG_CONT:
                nic_config_rss(nic, &mbx.rss_cfg);
@@ -1039,7 +1055,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
        case NIC_MBOX_MSG_CFG_DONE:
                /* Last message of VF config msg sequence */
                nic_enable_vf(nic, vf, true);
-               goto unlock;
+               break;
        case NIC_MBOX_MSG_SHUTDOWN:
                /* First msg in VF teardown sequence */
                if (vf >= nic->num_vf_en)
@@ -1049,19 +1065,19 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
                break;
        case NIC_MBOX_MSG_ALLOC_SQS:
                nic_alloc_sqs(nic, &mbx.sqs_alloc);
-               goto unlock;
+               return;
        case NIC_MBOX_MSG_NICVF_PTR:
                nic->nicvf[vf] = mbx.nicvf.nicvf;
                break;
        case NIC_MBOX_MSG_PNICVF_PTR:
                nic_send_pnicvf(nic, vf);
-               goto unlock;
+               return;
        case NIC_MBOX_MSG_SNICVF_PTR:
                nic_send_snicvf(nic, &mbx.nicvf);
-               goto unlock;
+               return;
        case NIC_MBOX_MSG_BGX_STATS:
                nic_get_bgx_stats(nic, &mbx.bgx_stats);
-               goto unlock;
+               return;
        case NIC_MBOX_MSG_LOOPBACK:
                ret = nic_config_loopback(nic, &mbx.lbk);
                break;
@@ -1070,7 +1086,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
                break;
        case NIC_MBOX_MSG_PFC:
                nic_pause_frame(nic, vf, &mbx.pfc);
-               goto unlock;
+               return;
        case NIC_MBOX_MSG_PTP_CFG:
                nic_config_timestamp(nic, vf, &mbx.ptp);
                break;
@@ -1094,7 +1110,7 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
                bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
                lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
                bgx_set_dmac_cam_filter(nic->node, bgx, lmac,
-                                       mbx.xcast.data.mac,
+                                       mbx.xcast.mac,
                                        vf < NIC_VF_PER_MBX_REG ? vf :
                                        vf - NIC_VF_PER_MBX_REG);
                break;
@@ -1106,8 +1122,15 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
                }
                bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
                lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
-               bgx_set_xcast_mode(nic->node, bgx, lmac, mbx.xcast.data.mode);
+               bgx_set_xcast_mode(nic->node, bgx, lmac, mbx.xcast.mode);
                break;
+       case NIC_MBOX_MSG_BGX_LINK_CHANGE:
+               if (vf >= nic->num_vf_en) {
+                       ret = -1; /* NACK */
+                       break;
+               }
+               nic_link_status_get(nic, vf);
+               return;
        default:
                dev_err(&nic->pdev->dev,
                        "Invalid msg from VF%d, msg 0x%x\n", vf, mbx.msg.msg);
@@ -1121,8 +1144,6 @@ static void nic_handle_mbx_intr(struct nicpf *nic, int vf)
                        mbx.msg.msg, vf);
                nic_mbx_send_nack(nic, vf);
        }
-unlock:
-       nic->mbx_lock[vf] = false;
 }
 
 static irqreturn_t nic_mbx_intr_handler(int irq, void *nic_irq)
@@ -1270,52 +1291,6 @@ static int nic_sriov_init(struct pci_dev *pdev, struct nicpf *nic)
        return 0;
 }
 
-/* Poll for BGX LMAC link status and update corresponding VF
- * if there is a change, valid only if internal L2 switch
- * is not present otherwise VF link is always treated as up
- */
-static void nic_poll_for_link(struct work_struct *work)
-{
-       union nic_mbx mbx = {};
-       struct nicpf *nic;
-       struct bgx_link_status link;
-       u8 vf, bgx, lmac;
-
-       nic = container_of(work, struct nicpf, dwork.work);
-
-       mbx.link_status.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE;
-
-       for (vf = 0; vf < nic->num_vf_en; vf++) {
-               /* Poll only if VF is UP */
-               if (!nic->vf_enabled[vf])
-                       continue;
-
-               /* Get BGX, LMAC indices for the VF */
-               bgx = NIC_GET_BGX_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
-               lmac = NIC_GET_LMAC_FROM_VF_LMAC_MAP(nic->vf_lmac_map[vf]);
-               /* Get interface link status */
-               bgx_get_lmac_link_state(nic->node, bgx, lmac, &link);
-
-               /* Inform VF only if link status changed */
-               if (nic->link[vf] == link.link_up)
-                       continue;
-
-               if (!nic->mbx_lock[vf]) {
-                       nic->link[vf] = link.link_up;
-                       nic->duplex[vf] = link.duplex;
-                       nic->speed[vf] = link.speed;
-
-                       /* Send a mbox message to VF with current link status */
-                       mbx.link_status.link_up = link.link_up;
-                       mbx.link_status.duplex = link.duplex;
-                       mbx.link_status.speed = link.speed;
-                       mbx.link_status.mac_type = link.mac_type;
-                       nic_send_msg_to_vf(nic, vf, &mbx);
-               }
-       }
-       queue_delayed_work(nic->check_link, &nic->dwork, HZ * 2);
-}
-
 static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 {
        struct device *dev = &pdev->dev;
@@ -1384,18 +1359,6 @@ static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (!nic->vf_lmac_map)
                goto err_release_regions;
 
-       nic->link = devm_kmalloc_array(dev, max_lmac, sizeof(u8), GFP_KERNEL);
-       if (!nic->link)
-               goto err_release_regions;
-
-       nic->duplex = devm_kmalloc_array(dev, max_lmac, sizeof(u8), GFP_KERNEL);
-       if (!nic->duplex)
-               goto err_release_regions;
-
-       nic->speed = devm_kmalloc_array(dev, max_lmac, sizeof(u32), GFP_KERNEL);
-       if (!nic->speed)
-               goto err_release_regions;
-
        /* Initialize hardware */
        nic_init_hw(nic);
 
@@ -1411,22 +1374,8 @@ static int nic_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        if (err)
                goto err_unregister_interrupts;
 
-       /* Register a physical link status poll fn() */
-       nic->check_link = alloc_workqueue("check_link_status",
-                                         WQ_UNBOUND | WQ_MEM_RECLAIM, 1);
-       if (!nic->check_link) {
-               err = -ENOMEM;
-               goto err_disable_sriov;
-       }
-
-       INIT_DELAYED_WORK(&nic->dwork, nic_poll_for_link);
-       queue_delayed_work(nic->check_link, &nic->dwork, 0);
-
        return 0;
 
-err_disable_sriov:
-       if (nic->flags & NIC_SRIOV_ENABLED)
-               pci_disable_sriov(pdev);
 err_unregister_interrupts:
        nic_unregister_interrupts(nic);
 err_release_regions:
@@ -1447,12 +1396,6 @@ static void nic_remove(struct pci_dev *pdev)
        if (nic->flags & NIC_SRIOV_ENABLED)
                pci_disable_sriov(pdev);
 
-       if (nic->check_link) {
-               /* Destroy work Queue */
-               cancel_delayed_work_sync(&nic->dwork);
-               destroy_workqueue(nic->check_link);
-       }
-
        nic_unregister_interrupts(nic);
        pci_release_regions(pdev);
 
index 88f8a8f..503cfad 100644 (file)
@@ -68,9 +68,6 @@ module_param(cpi_alg, int, 0444);
 MODULE_PARM_DESC(cpi_alg,
                 "PFC algorithm (0=none, 1=VLAN, 2=VLAN16, 3=IP Diffserv)");
 
-/* workqueue for handling kernel ndo_set_rx_mode() calls */
-static struct workqueue_struct *nicvf_rx_mode_wq;
-
 static inline u8 nicvf_netdev_qidx(struct nicvf *nic, u8 qidx)
 {
        if (nic->sqs_mode)
@@ -127,6 +124,9 @@ int nicvf_send_msg_to_pf(struct nicvf *nic, union nic_mbx *mbx)
 {
        int timeout = NIC_MBOX_MSG_TIMEOUT;
        int sleep = 10;
+       int ret = 0;
+
+       mutex_lock(&nic->rx_mode_mtx);
 
        nic->pf_acked = false;
        nic->pf_nacked = false;
@@ -139,7 +139,8 @@ int nicvf_send_msg_to_pf(struct nicvf *nic, union nic_mbx *mbx)
                        netdev_err(nic->netdev,
                                   "PF NACK to mbox msg 0x%02x from VF%d\n",
                                   (mbx->msg.msg & 0xFF), nic->vf_id);
-                       return -EINVAL;
+                       ret = -EINVAL;
+                       break;
                }
                msleep(sleep);
                if (nic->pf_acked)
@@ -149,10 +150,12 @@ int nicvf_send_msg_to_pf(struct nicvf *nic, union nic_mbx *mbx)
                        netdev_err(nic->netdev,
                                   "PF didn't ACK to mbox msg 0x%02x from VF%d\n",
                                   (mbx->msg.msg & 0xFF), nic->vf_id);
-                       return -EBUSY;
+                       ret = -EBUSY;
+                       break;
                }
        }
-       return 0;
+       mutex_unlock(&nic->rx_mode_mtx);
+       return ret;
 }
 
 /* Checks if VF is able to comminicate with PF
@@ -172,6 +175,17 @@ static int nicvf_check_pf_ready(struct nicvf *nic)
        return 1;
 }
 
+static void nicvf_send_cfg_done(struct nicvf *nic)
+{
+       union nic_mbx mbx = {};
+
+       mbx.msg.msg = NIC_MBOX_MSG_CFG_DONE;
+       if (nicvf_send_msg_to_pf(nic, &mbx)) {
+               netdev_err(nic->netdev,
+                          "PF didn't respond to CFG DONE msg\n");
+       }
+}
+
 static void nicvf_read_bgx_stats(struct nicvf *nic, struct bgx_stats_msg *bgx)
 {
        if (bgx->rx)
@@ -228,21 +242,24 @@ static void  nicvf_handle_mbx_intr(struct nicvf *nic)
                break;
        case NIC_MBOX_MSG_BGX_LINK_CHANGE:
                nic->pf_acked = true;
-               nic->link_up = mbx.link_status.link_up;
-               nic->duplex = mbx.link_status.duplex;
-               nic->speed = mbx.link_status.speed;
-               nic->mac_type = mbx.link_status.mac_type;
-               if (nic->link_up) {
-                       netdev_info(nic->netdev, "Link is Up %d Mbps %s duplex\n",
-                                   nic->speed,
-                                   nic->duplex == DUPLEX_FULL ?
-                                   "Full" : "Half");
-                       netif_carrier_on(nic->netdev);
-                       netif_tx_start_all_queues(nic->netdev);
-               } else {
-                       netdev_info(nic->netdev, "Link is Down\n");
-                       netif_carrier_off(nic->netdev);
-                       netif_tx_stop_all_queues(nic->netdev);
+               if (nic->link_up != mbx.link_status.link_up) {
+                       nic->link_up = mbx.link_status.link_up;
+                       nic->duplex = mbx.link_status.duplex;
+                       nic->speed = mbx.link_status.speed;
+                       nic->mac_type = mbx.link_status.mac_type;
+                       if (nic->link_up) {
+                               netdev_info(nic->netdev,
+                                           "Link is Up %d Mbps %s duplex\n",
+                                           nic->speed,
+                                           nic->duplex == DUPLEX_FULL ?
+                                           "Full" : "Half");
+                               netif_carrier_on(nic->netdev);
+                               netif_tx_start_all_queues(nic->netdev);
+                       } else {
+                               netdev_info(nic->netdev, "Link is Down\n");
+                               netif_carrier_off(nic->netdev);
+                               netif_tx_stop_all_queues(nic->netdev);
+                       }
                }
                break;
        case NIC_MBOX_MSG_ALLOC_SQS:
@@ -1311,6 +1328,11 @@ int nicvf_stop(struct net_device *netdev)
        struct nicvf_cq_poll *cq_poll = NULL;
        union nic_mbx mbx = {};
 
+       cancel_delayed_work_sync(&nic->link_change_work);
+
+       /* wait till all queued set_rx_mode tasks completes */
+       drain_workqueue(nic->nicvf_rx_mode_wq);
+
        mbx.msg.msg = NIC_MBOX_MSG_SHUTDOWN;
        nicvf_send_msg_to_pf(nic, &mbx);
 
@@ -1410,13 +1432,27 @@ static int nicvf_update_hw_max_frs(struct nicvf *nic, int mtu)
        return nicvf_send_msg_to_pf(nic, &mbx);
 }
 
+static void nicvf_link_status_check_task(struct work_struct *work_arg)
+{
+       struct nicvf *nic = container_of(work_arg,
+                                        struct nicvf,
+                                        link_change_work.work);
+       union nic_mbx mbx = {};
+       mbx.msg.msg = NIC_MBOX_MSG_BGX_LINK_CHANGE;
+       nicvf_send_msg_to_pf(nic, &mbx);
+       queue_delayed_work(nic->nicvf_rx_mode_wq,
+                          &nic->link_change_work, 2 * HZ);
+}
+
 int nicvf_open(struct net_device *netdev)
 {
        int cpu, err, qidx;
        struct nicvf *nic = netdev_priv(netdev);
        struct queue_set *qs = nic->qs;
        struct nicvf_cq_poll *cq_poll = NULL;
-       union nic_mbx mbx = {};
+
+       /* wait till all queued set_rx_mode tasks completes if any */
+       drain_workqueue(nic->nicvf_rx_mode_wq);
 
        netif_carrier_off(netdev);
 
@@ -1512,8 +1548,12 @@ int nicvf_open(struct net_device *netdev)
                nicvf_enable_intr(nic, NICVF_INTR_RBDR, qidx);
 
        /* Send VF config done msg to PF */
-       mbx.msg.msg = NIC_MBOX_MSG_CFG_DONE;
-       nicvf_write_to_mbx(nic, &mbx);
+       nicvf_send_cfg_done(nic);
+
+       INIT_DELAYED_WORK(&nic->link_change_work,
+                         nicvf_link_status_check_task);
+       queue_delayed_work(nic->nicvf_rx_mode_wq,
+                          &nic->link_change_work, 0);
 
        return 0;
 cleanup:
@@ -1941,15 +1981,17 @@ static void __nicvf_set_rx_mode_task(u8 mode, struct xcast_addr_list *mc_addrs,
 
        /* flush DMAC filters and reset RX mode */
        mbx.xcast.msg = NIC_MBOX_MSG_RESET_XCAST;
-       nicvf_send_msg_to_pf(nic, &mbx);
+       if (nicvf_send_msg_to_pf(nic, &mbx) < 0)
+               goto free_mc;
 
        if (mode & BGX_XCAST_MCAST_FILTER) {
                /* once enabling filtering, we need to signal to PF to add
                 * its' own LMAC to the filter to accept packets for it.
                 */
                mbx.xcast.msg = NIC_MBOX_MSG_ADD_MCAST;
-               mbx.xcast.data.mac = 0;
-               nicvf_send_msg_to_pf(nic, &mbx);
+               mbx.xcast.mac = 0;
+               if (nicvf_send_msg_to_pf(nic, &mbx) < 0)
+                       goto free_mc;
        }
 
        /* check if we have any specific MACs to be added to PF DMAC filter */
@@ -1957,23 +1999,25 @@ static void __nicvf_set_rx_mode_task(u8 mode, struct xcast_addr_list *mc_addrs,
                /* now go through kernel list of MACs and add them one by one */
                for (idx = 0; idx < mc_addrs->count; idx++) {
                        mbx.xcast.msg = NIC_MBOX_MSG_ADD_MCAST;
-                       mbx.xcast.data.mac = mc_addrs->mc[idx];
-                       nicvf_send_msg_to_pf(nic, &mbx);
+                       mbx.xcast.mac = mc_addrs->mc[idx];
+                       if (nicvf_send_msg_to_pf(nic, &mbx) < 0)
+                               goto free_mc;
                }
-               kfree(mc_addrs);
        }
 
        /* and finally set rx mode for PF accordingly */
        mbx.xcast.msg = NIC_MBOX_MSG_SET_XCAST;
-       mbx.xcast.data.mode = mode;
+       mbx.xcast.mode = mode;
 
        nicvf_send_msg_to_pf(nic, &mbx);
+free_mc:
+       kfree(mc_addrs);
 }
 
 static void nicvf_set_rx_mode_task(struct work_struct *work_arg)
 {
        struct nicvf_work *vf_work = container_of(work_arg, struct nicvf_work,
-                                                 work.work);
+                                                 work);
        struct nicvf *nic = container_of(vf_work, struct nicvf, rx_mode_work);
        u8 mode;
        struct xcast_addr_list *mc;
@@ -2030,7 +2074,7 @@ static void nicvf_set_rx_mode(struct net_device *netdev)
        kfree(nic->rx_mode_work.mc);
        nic->rx_mode_work.mc = mc_list;
        nic->rx_mode_work.mode = mode;
-       queue_delayed_work(nicvf_rx_mode_wq, &nic->rx_mode_work.work, 0);
+       queue_work(nic->nicvf_rx_mode_wq, &nic->rx_mode_work.work);
        spin_unlock(&nic->rx_mode_wq_lock);
 }
 
@@ -2187,8 +2231,12 @@ static int nicvf_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
 
        INIT_WORK(&nic->reset_task, nicvf_reset_task);
 
-       INIT_DELAYED_WORK(&nic->rx_mode_work.work, nicvf_set_rx_mode_task);
+       nic->nicvf_rx_mode_wq = alloc_ordered_workqueue("nicvf_rx_mode_wq_VF%d",
+                                                       WQ_MEM_RECLAIM,
+                                                       nic->vf_id);
+       INIT_WORK(&nic->rx_mode_work.work, nicvf_set_rx_mode_task);
        spin_lock_init(&nic->rx_mode_wq_lock);
+       mutex_init(&nic->rx_mode_mtx);
 
        err = register_netdev(netdev);
        if (err) {
@@ -2228,13 +2276,15 @@ static void nicvf_remove(struct pci_dev *pdev)
        nic = netdev_priv(netdev);
        pnetdev = nic->pnicvf->netdev;
 
-       cancel_delayed_work_sync(&nic->rx_mode_work.work);
-
        /* Check if this Qset is assigned to different VF.
         * If yes, clean primary and all secondary Qsets.
         */
        if (pnetdev && (pnetdev->reg_state == NETREG_REGISTERED))
                unregister_netdev(pnetdev);
+       if (nic->nicvf_rx_mode_wq) {
+               destroy_workqueue(nic->nicvf_rx_mode_wq);
+               nic->nicvf_rx_mode_wq = NULL;
+       }
        nicvf_unregister_interrupts(nic);
        pci_set_drvdata(pdev, NULL);
        if (nic->drv_stats)
@@ -2261,17 +2311,11 @@ static struct pci_driver nicvf_driver = {
 static int __init nicvf_init_module(void)
 {
        pr_info("%s, ver %s\n", DRV_NAME, DRV_VERSION);
-       nicvf_rx_mode_wq = alloc_ordered_workqueue("nicvf_generic",
-                                                  WQ_MEM_RECLAIM);
        return pci_register_driver(&nicvf_driver);
 }
 
 static void __exit nicvf_cleanup_module(void)
 {
-       if (nicvf_rx_mode_wq) {
-               destroy_workqueue(nicvf_rx_mode_wq);
-               nicvf_rx_mode_wq = NULL;
-       }
        pci_unregister_driver(&nicvf_driver);
 }
 
index fcaf18f..5b4d3ba 100644 (file)
@@ -59,7 +59,7 @@ static int nicvf_alloc_q_desc_mem(struct nicvf *nic, struct q_desc_mem *dmem,
        dmem->q_len = q_len;
        dmem->size = (desc_size * q_len) + align_bytes;
        /* Save address, need it while freeing */
-       dmem->unalign_base = dma_zalloc_coherent(&nic->pdev->dev, dmem->size,
+       dmem->unalign_base = dma_alloc_coherent(&nic->pdev->dev, dmem->size,
                                                &dmem->dma, GFP_KERNEL);
        if (!dmem->unalign_base)
                return -ENOMEM;
index e337da6..673c57b 100644 (file)
@@ -1217,7 +1217,7 @@ static void bgx_init_hw(struct bgx *bgx)
 
        /* Disable MAC steering (NCSI traffic) */
        for (i = 0; i < RX_TRAFFIC_STEER_RULE_COUNT; i++)
-               bgx_reg_write(bgx, 0, BGX_CMR_RX_STREERING + (i * 8), 0x00);
+               bgx_reg_write(bgx, 0, BGX_CMR_RX_STEERING + (i * 8), 0x00);
 }
 
 static u8 bgx_get_lane2sds_cfg(struct bgx *bgx, struct lmac *lmac)
index cbdd20b..5cbc54e 100644 (file)
@@ -60,7 +60,7 @@
 #define  RX_DMACX_CAM_EN                       BIT_ULL(48)
 #define  RX_DMACX_CAM_LMACID(x)                        (((u64)x) << 49)
 #define  RX_DMAC_COUNT                         32
-#define BGX_CMR_RX_STREERING           0x300
+#define BGX_CMR_RX_STEERING            0x300
 #define  RX_TRAFFIC_STEER_RULE_COUNT           8
 #define BGX_CMR_CHAN_MSK_AND           0x450
 #define BGX_CMR_BIST_STATUS            0x460
index 20b6e1b..89db739 100644 (file)
@@ -620,7 +620,7 @@ static void *alloc_ring(struct pci_dev *pdev, size_t nelem, size_t elem_size,
 {
        size_t len = nelem * elem_size;
        void *s = NULL;
-       void *p = dma_zalloc_coherent(&pdev->dev, len, phys, GFP_KERNEL);
+       void *p = dma_alloc_coherent(&pdev->dev, len, phys, GFP_KERNEL);
 
        if (!p)
                return NULL;
@@ -2381,7 +2381,7 @@ no_mem:
                                        lro_add_page(adap, qs, fl,
                                                     G_RSPD_LEN(len),
                                                     flags & F_RSPD_EOP);
-                                        goto next_fl;
+                                       goto next_fl;
                                }
 
                                skb = get_packet_pg(adap, fl, q,
@@ -3214,11 +3214,13 @@ void t3_start_sge_timers(struct adapter *adap)
        for (i = 0; i < SGE_QSETS; ++i) {
                struct sge_qset *q = &adap->sge.qs[i];
 
-       if (q->tx_reclaim_timer.function)
-               mod_timer(&q->tx_reclaim_timer, jiffies + TX_RECLAIM_PERIOD);
+               if (q->tx_reclaim_timer.function)
+                       mod_timer(&q->tx_reclaim_timer,
+                                 jiffies + TX_RECLAIM_PERIOD);
 
-       if (q->rx_reclaim_timer.function)
-               mod_timer(&q->rx_reclaim_timer, jiffies + RX_RECLAIM_PERIOD);
+               if (q->rx_reclaim_timer.function)
+                       mod_timer(&q->rx_reclaim_timer,
+                                 jiffies + RX_RECLAIM_PERIOD);
        }
 }
 
index 080918a..0a9f2c5 100644 (file)
@@ -1082,7 +1082,7 @@ int t3_check_fw_version(struct adapter *adapter)
                CH_WARN(adapter, "found newer FW version(%u.%u), "
                        "driver compiled for version %u.%u\n", major, minor,
                        FW_VERSION_MAJOR, FW_VERSION_MINOR);
-                       return 0;
+               return 0;
        }
        return -EINVAL;
 }
@@ -3619,7 +3619,7 @@ int t3_reset_adapter(struct adapter *adapter)
 
 static int init_parity(struct adapter *adap)
 {
-               int i, err, addr;
+       int i, err, addr;
 
        if (t3_read_reg(adap, A_SG_CONTEXT_CMD) & F_CONTEXT_CMD_BUSY)
                return -EBUSY;
@@ -3806,6 +3806,6 @@ int t3_replay_prep_adapter(struct adapter *adapter)
                p->phy.ops->power_down(&p->phy, 1);
        }
 
-return 0;
+       return 0;
 }
 
index 9f9d6ca..58a039c 100644 (file)
@@ -378,10 +378,10 @@ static void cxgb4_init_ptp_timer(struct adapter *adapter)
        int err;
 
        memset(&c, 0, sizeof(c));
-               c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PTP_CMD) |
-                                            FW_CMD_REQUEST_F |
-                                            FW_CMD_WRITE_F |
-                                            FW_PTP_CMD_PORTID_V(0));
+       c.op_to_portid = cpu_to_be32(FW_CMD_OP_V(FW_PTP_CMD) |
+                                    FW_CMD_REQUEST_F |
+                                    FW_CMD_WRITE_F |
+                                    FW_PTP_CMD_PORTID_V(0));
        c.retval_len16 = cpu_to_be32(FW_CMD_LEN16_V(sizeof(c) / 16));
        c.u.scmd.sc = FW_PTP_SC_INIT_TIMER;
 
index 9a6065a..b365459 100644 (file)
@@ -78,7 +78,7 @@ static void free_msix_idx_in_bmap(struct adapter *adap, unsigned int msix_idx)
        unsigned long flags;
 
        spin_lock_irqsave(&bmap->lock, flags);
-        __clear_bit(msix_idx, bmap->msix_bmap);
+       __clear_bit(msix_idx, bmap->msix_bmap);
        spin_unlock_irqrestore(&bmap->lock, flags);
 }
 
@@ -660,6 +660,7 @@ static void uld_init(struct adapter *adap, struct cxgb4_lld_info *lld)
        lld->cclk_ps = 1000000000 / adap->params.vpd.cclk;
        lld->udb_density = 1 << adap->params.sge.eq_qpp;
        lld->ucq_density = 1 << adap->params.sge.iq_qpp;
+       lld->sge_host_page_size = 1 << (adap->params.sge.hps + 10);
        lld->filt_mode = adap->params.tp.vlan_pri_map;
        /* MODQ_REQ_MAP sets queues 0-3 to chan 0-3 */
        for (i = 0; i < NCHAN; i++)
index 5fa9a2d..21da34a 100644 (file)
@@ -336,6 +336,7 @@ struct cxgb4_lld_info {
        unsigned int cclk_ps;                /* Core clock period in psec */
        unsigned short udb_density;          /* # of user DB/page */
        unsigned short ucq_density;          /* # of user CQs/page */
+       unsigned int sge_host_page_size;     /* SGE host page size */
        unsigned short filt_mode;            /* filter optional components */
        unsigned short tx_modq[NCHAN];       /* maps each tx channel to a */
                                             /* scheduler queue */
index b901884..fc0bc64 100644 (file)
@@ -694,7 +694,7 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t elem_size,
 {
        size_t len = nelem * elem_size + stat_size;
        void *s = NULL;
-       void *p = dma_zalloc_coherent(dev, len, phys, GFP_KERNEL);
+       void *p = dma_alloc_coherent(dev, len, phys, GFP_KERNEL);
 
        if (!p)
                return NULL;
index e8c3429..2b03f61 100644 (file)
@@ -3794,7 +3794,7 @@ int t4_load_phy_fw(struct adapter *adap,
        /* If we have version number support, then check to see if the adapter
         * already has up-to-date PHY firmware loaded.
         */
-        if (phy_fw_version) {
+       if (phy_fw_version) {
                new_phy_fw_vers = phy_fw_version(phy_fw_data, phy_fw_size);
                ret = t4_phy_fw_ver(adap, &cur_phy_fw_ver);
                if (ret < 0)
index 3007e1a..1d534f0 100644 (file)
@@ -756,7 +756,7 @@ static void *alloc_ring(struct device *dev, size_t nelem, size_t hwsize,
         * Allocate the hardware ring and PCI DMA bus address space for said.
         */
        size_t hwlen = nelem * hwsize + stat_size;
-       void *hwring = dma_zalloc_coherent(dev, hwlen, busaddrp, GFP_KERNEL);
+       void *hwring = dma_alloc_coherent(dev, hwlen, busaddrp, GFP_KERNEL);
 
        if (!hwring)
                return NULL;
index 60641e2..9a7f70d 100644 (file)
@@ -1434,7 +1434,8 @@ static void enic_rq_indicate_buf(struct vnic_rq *rq,
                 * csum is correct or is zero.
                 */
                if ((netdev->features & NETIF_F_RXCSUM) && !csum_not_calc &&
-                   tcp_udp_csum_ok && ipv4_csum_ok && outer_csum_ok) {
+                   tcp_udp_csum_ok && outer_csum_ok &&
+                   (ipv4_csum_ok || ipv6)) {
                        skb->ip_summed = CHECKSUM_UNNECESSARY;
                        skb->csum_level = encap;
                }
index 13430f7..f1a2da1 100644 (file)
@@ -585,7 +585,7 @@ static void de_tx (struct de_private *de)
                                netif_dbg(de, tx_done, de->dev,
                                          "tx done, slot %d\n", tx_tail);
                        }
-                       dev_kfree_skb_irq(skb);
+                       dev_consume_skb_irq(skb);
                }
 
 next:
index 1e9d882..59a7f0b 100644 (file)
@@ -1808,9 +1808,9 @@ int be_cmd_get_fat_dump(struct be_adapter *adapter, u32 buf_len, void *buf)
        total_size = buf_len;
 
        get_fat_cmd.size = sizeof(struct be_cmd_req_get_fat) + 60*1024;
-       get_fat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
-                                            get_fat_cmd.size,
-                                            &get_fat_cmd.dma, GFP_ATOMIC);
+       get_fat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+                                           get_fat_cmd.size,
+                                           &get_fat_cmd.dma, GFP_ATOMIC);
        if (!get_fat_cmd.va)
                return -ENOMEM;
 
@@ -2302,8 +2302,8 @@ int be_cmd_read_port_transceiver_data(struct be_adapter *adapter,
                return -EINVAL;
 
        cmd.size = sizeof(struct be_cmd_resp_port_type);
-       cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
-                                    GFP_ATOMIC);
+       cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+                                   GFP_ATOMIC);
        if (!cmd.va) {
                dev_err(&adapter->pdev->dev, "Memory allocation failed\n");
                return -ENOMEM;
@@ -3066,8 +3066,8 @@ int lancer_fw_download(struct be_adapter *adapter,
 
        flash_cmd.size = sizeof(struct lancer_cmd_req_write_object)
                                + LANCER_FW_DOWNLOAD_CHUNK;
-       flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size,
-                                          &flash_cmd.dma, GFP_KERNEL);
+       flash_cmd.va = dma_alloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
+                                         GFP_KERNEL);
        if (!flash_cmd.va)
                return -ENOMEM;
 
@@ -3184,8 +3184,8 @@ int be_fw_download(struct be_adapter *adapter, const struct firmware *fw)
        }
 
        flash_cmd.size = sizeof(struct be_cmd_write_flashrom);
-       flash_cmd.va = dma_zalloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
-                                          GFP_KERNEL);
+       flash_cmd.va = dma_alloc_coherent(dev, flash_cmd.size, &flash_cmd.dma,
+                                         GFP_KERNEL);
        if (!flash_cmd.va)
                return -ENOMEM;
 
@@ -3435,8 +3435,8 @@ int be_cmd_get_phy_info(struct be_adapter *adapter)
                goto err;
        }
        cmd.size = sizeof(struct be_cmd_req_get_phy_info);
-       cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
-                                    GFP_ATOMIC);
+       cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+                                   GFP_ATOMIC);
        if (!cmd.va) {
                dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
                status = -ENOMEM;
@@ -3522,9 +3522,9 @@ int be_cmd_get_cntl_attributes(struct be_adapter *adapter)
 
        memset(&attribs_cmd, 0, sizeof(struct be_dma_mem));
        attribs_cmd.size = sizeof(struct be_cmd_resp_cntl_attribs);
-       attribs_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
-                                            attribs_cmd.size,
-                                            &attribs_cmd.dma, GFP_ATOMIC);
+       attribs_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+                                           attribs_cmd.size,
+                                           &attribs_cmd.dma, GFP_ATOMIC);
        if (!attribs_cmd.va) {
                dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
                status = -ENOMEM;
@@ -3699,10 +3699,10 @@ int be_cmd_get_mac_from_list(struct be_adapter *adapter, u8 *mac,
 
        memset(&get_mac_list_cmd, 0, sizeof(struct be_dma_mem));
        get_mac_list_cmd.size = sizeof(struct be_cmd_resp_get_mac_list);
-       get_mac_list_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
-                                                 get_mac_list_cmd.size,
-                                                 &get_mac_list_cmd.dma,
-                                                 GFP_ATOMIC);
+       get_mac_list_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+                                                get_mac_list_cmd.size,
+                                                &get_mac_list_cmd.dma,
+                                                GFP_ATOMIC);
 
        if (!get_mac_list_cmd.va) {
                dev_err(&adapter->pdev->dev,
@@ -3829,8 +3829,8 @@ int be_cmd_set_mac_list(struct be_adapter *adapter, u8 *mac_array,
 
        memset(&cmd, 0, sizeof(struct be_dma_mem));
        cmd.size = sizeof(struct be_cmd_req_set_mac_list);
-       cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
-                                    GFP_KERNEL);
+       cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+                                   GFP_KERNEL);
        if (!cmd.va)
                return -ENOMEM;
 
@@ -4035,8 +4035,8 @@ int be_cmd_get_acpi_wol_cap(struct be_adapter *adapter)
 
        memset(&cmd, 0, sizeof(struct be_dma_mem));
        cmd.size = sizeof(struct be_cmd_resp_acpi_wol_magic_config_v1);
-       cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
-                                    GFP_ATOMIC);
+       cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+                                   GFP_ATOMIC);
        if (!cmd.va) {
                dev_err(&adapter->pdev->dev, "Memory allocation failure\n");
                status = -ENOMEM;
@@ -4089,9 +4089,9 @@ int be_cmd_set_fw_log_level(struct be_adapter *adapter, u32 level)
 
        memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
        extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
-       extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
-                                           extfat_cmd.size, &extfat_cmd.dma,
-                                           GFP_ATOMIC);
+       extfat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+                                          extfat_cmd.size, &extfat_cmd.dma,
+                                          GFP_ATOMIC);
        if (!extfat_cmd.va)
                return -ENOMEM;
 
@@ -4127,9 +4127,9 @@ int be_cmd_get_fw_log_level(struct be_adapter *adapter)
 
        memset(&extfat_cmd, 0, sizeof(struct be_dma_mem));
        extfat_cmd.size = sizeof(struct be_cmd_resp_get_ext_fat_caps);
-       extfat_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
-                                           extfat_cmd.size, &extfat_cmd.dma,
-                                           GFP_ATOMIC);
+       extfat_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+                                          extfat_cmd.size, &extfat_cmd.dma,
+                                          GFP_ATOMIC);
 
        if (!extfat_cmd.va) {
                dev_err(&adapter->pdev->dev, "%s: Memory allocation failure\n",
@@ -4354,8 +4354,8 @@ int be_cmd_get_func_config(struct be_adapter *adapter, struct be_resources *res)
 
        memset(&cmd, 0, sizeof(struct be_dma_mem));
        cmd.size = sizeof(struct be_cmd_resp_get_func_config);
-       cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
-                                    GFP_ATOMIC);
+       cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+                                   GFP_ATOMIC);
        if (!cmd.va) {
                dev_err(&adapter->pdev->dev, "Memory alloc failure\n");
                status = -ENOMEM;
@@ -4452,8 +4452,8 @@ int be_cmd_get_profile_config(struct be_adapter *adapter,
 
        memset(&cmd, 0, sizeof(struct be_dma_mem));
        cmd.size = sizeof(struct be_cmd_resp_get_profile_config);
-       cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
-                                    GFP_ATOMIC);
+       cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+                                   GFP_ATOMIC);
        if (!cmd.va)
                return -ENOMEM;
 
@@ -4539,8 +4539,8 @@ static int be_cmd_set_profile_config(struct be_adapter *adapter, void *desc,
 
        memset(&cmd, 0, sizeof(struct be_dma_mem));
        cmd.size = sizeof(struct be_cmd_req_set_profile_config);
-       cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
-                                    GFP_ATOMIC);
+       cmd.va = dma_alloc_coherent(&adapter->pdev->dev, cmd.size, &cmd.dma,
+                                   GFP_ATOMIC);
        if (!cmd.va)
                return -ENOMEM;
 
index 3f6749f..4c21834 100644 (file)
@@ -274,8 +274,8 @@ static int lancer_cmd_read_file(struct be_adapter *adapter, u8 *file_name,
        int status = 0;
 
        read_cmd.size = LANCER_READ_FILE_CHUNK;
-       read_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev, read_cmd.size,
-                                         &read_cmd.dma, GFP_ATOMIC);
+       read_cmd.va = dma_alloc_coherent(&adapter->pdev->dev, read_cmd.size,
+                                        &read_cmd.dma, GFP_ATOMIC);
 
        if (!read_cmd.va) {
                dev_err(&adapter->pdev->dev,
@@ -815,7 +815,7 @@ static int be_set_wol(struct net_device *netdev, struct ethtool_wolinfo *wol)
        }
 
        cmd.size = sizeof(struct be_cmd_req_acpi_wol_magic_config);
-       cmd.va = dma_zalloc_coherent(dev, cmd.size, &cmd.dma, GFP_KERNEL);
+       cmd.va = dma_alloc_coherent(dev, cmd.size, &cmd.dma, GFP_KERNEL);
        if (!cmd.va)
                return -ENOMEM;
 
@@ -851,9 +851,9 @@ static int be_test_ddr_dma(struct be_adapter *adapter)
        };
 
        ddrdma_cmd.size = sizeof(struct be_cmd_req_ddrdma_test);
-       ddrdma_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
-                                           ddrdma_cmd.size, &ddrdma_cmd.dma,
-                                           GFP_KERNEL);
+       ddrdma_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+                                          ddrdma_cmd.size, &ddrdma_cmd.dma,
+                                          GFP_KERNEL);
        if (!ddrdma_cmd.va)
                return -ENOMEM;
 
@@ -1014,9 +1014,9 @@ static int be_read_eeprom(struct net_device *netdev,
 
        memset(&eeprom_cmd, 0, sizeof(struct be_dma_mem));
        eeprom_cmd.size = sizeof(struct be_cmd_req_seeprom_read);
-       eeprom_cmd.va = dma_zalloc_coherent(&adapter->pdev->dev,
-                                           eeprom_cmd.size, &eeprom_cmd.dma,
-                                           GFP_KERNEL);
+       eeprom_cmd.va = dma_alloc_coherent(&adapter->pdev->dev,
+                                          eeprom_cmd.size, &eeprom_cmd.dma,
+                                          GFP_KERNEL);
 
        if (!eeprom_cmd.va)
                return -ENOMEM;
index 852f5bf..d502690 100644 (file)
@@ -167,8 +167,8 @@ static int be_queue_alloc(struct be_adapter *adapter, struct be_queue_info *q,
        q->len = len;
        q->entry_size = entry_size;
        mem->size = len * entry_size;
-       mem->va = dma_zalloc_coherent(&adapter->pdev->dev, mem->size, &mem->dma,
-                                     GFP_KERNEL);
+       mem->va = dma_alloc_coherent(&adapter->pdev->dev, mem->size,
+                                    &mem->dma, GFP_KERNEL);
        if (!mem->va)
                return -ENOMEM;
        return 0;
@@ -5766,9 +5766,9 @@ static int be_drv_init(struct be_adapter *adapter)
        int status = 0;
 
        mbox_mem_alloc->size = sizeof(struct be_mcc_mailbox) + 16;
-       mbox_mem_alloc->va = dma_zalloc_coherent(dev, mbox_mem_alloc->size,
-                                                &mbox_mem_alloc->dma,
-                                                GFP_KERNEL);
+       mbox_mem_alloc->va = dma_alloc_coherent(dev, mbox_mem_alloc->size,
+                                               &mbox_mem_alloc->dma,
+                                               GFP_KERNEL);
        if (!mbox_mem_alloc->va)
                return -ENOMEM;
 
@@ -5777,8 +5777,8 @@ static int be_drv_init(struct be_adapter *adapter)
        mbox_mem_align->dma = PTR_ALIGN(mbox_mem_alloc->dma, 16);
 
        rx_filter->size = sizeof(struct be_cmd_req_rx_filter);
-       rx_filter->va = dma_zalloc_coherent(dev, rx_filter->size,
-                                           &rx_filter->dma, GFP_KERNEL);
+       rx_filter->va = dma_alloc_coherent(dev, rx_filter->size,
+                                          &rx_filter->dma, GFP_KERNEL);
        if (!rx_filter->va) {
                status = -ENOMEM;
                goto free_mbox;
@@ -5792,8 +5792,8 @@ static int be_drv_init(struct be_adapter *adapter)
                stats_cmd->size = sizeof(struct be_cmd_req_get_stats_v1);
        else
                stats_cmd->size = sizeof(struct be_cmd_req_get_stats_v2);
-       stats_cmd->va = dma_zalloc_coherent(dev, stats_cmd->size,
-                                           &stats_cmd->dma, GFP_KERNEL);
+       stats_cmd->va = dma_alloc_coherent(dev, stats_cmd->size,
+                                          &stats_cmd->dma, GFP_KERNEL);
        if (!stats_cmd->va) {
                status = -ENOMEM;
                goto free_rx_filter;
index 4d67322..3e5e971 100644 (file)
@@ -935,16 +935,14 @@ static int ftgmac100_alloc_rings(struct ftgmac100 *priv)
                return -ENOMEM;
 
        /* Allocate descriptors */
-       priv->rxdes = dma_zalloc_coherent(priv->dev,
-                                         MAX_RX_QUEUE_ENTRIES *
-                                         sizeof(struct ftgmac100_rxdes),
-                                         &priv->rxdes_dma, GFP_KERNEL);
+       priv->rxdes = dma_alloc_coherent(priv->dev,
+                                        MAX_RX_QUEUE_ENTRIES * sizeof(struct ftgmac100_rxdes),
+                                        &priv->rxdes_dma, GFP_KERNEL);
        if (!priv->rxdes)
                return -ENOMEM;
-       priv->txdes = dma_zalloc_coherent(priv->dev,
-                                         MAX_TX_QUEUE_ENTRIES *
-                                         sizeof(struct ftgmac100_txdes),
-                                         &priv->txdes_dma, GFP_KERNEL);
+       priv->txdes = dma_alloc_coherent(priv->dev,
+                                        MAX_TX_QUEUE_ENTRIES * sizeof(struct ftgmac100_txdes),
+                                        &priv->txdes_dma, GFP_KERNEL);
        if (!priv->txdes)
                return -ENOMEM;
 
index 084f24d..2a0e820 100644 (file)
@@ -734,10 +734,9 @@ static int ftmac100_alloc_buffers(struct ftmac100 *priv)
 {
        int i;
 
-       priv->descs = dma_zalloc_coherent(priv->dev,
-                                         sizeof(struct ftmac100_descs),
-                                         &priv->descs_dma_addr,
-                                         GFP_KERNEL);
+       priv->descs = dma_alloc_coherent(priv->dev,
+                                        sizeof(struct ftmac100_descs),
+                                        &priv->descs_dma_addr, GFP_KERNEL);
        if (!priv->descs)
                return -ENOMEM;
 
index f53090c..dfebc30 100644 (file)
@@ -2051,6 +2051,7 @@ dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
        bool nonlinear = skb_is_nonlinear(skb);
        struct rtnl_link_stats64 *percpu_stats;
        struct dpaa_percpu_priv *percpu_priv;
+       struct netdev_queue *txq;
        struct dpaa_priv *priv;
        struct qm_fd fd;
        int offset = 0;
@@ -2100,6 +2101,11 @@ dpaa_start_xmit(struct sk_buff *skb, struct net_device *net_dev)
        if (unlikely(err < 0))
                goto skb_to_fd_failed;
 
+       txq = netdev_get_tx_queue(net_dev, queue_mapping);
+
+       /* LLTX requires to do our own update of trans_start */
+       txq->trans_start = jiffies;
+
        if (priv->tx_tstamp && skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) {
                fd.cmd |= cpu_to_be32(FM_FD_CMD_UPD);
                skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
index 809a155..f6d244c 100644 (file)
@@ -9,8 +9,9 @@ config FSL_DPAA2_ETH
 
 config FSL_DPAA2_PTP_CLOCK
        tristate "Freescale DPAA2 PTP Clock"
-       depends on FSL_DPAA2_ETH && POSIX_TIMERS
-       select PTP_1588_CLOCK
+       depends on FSL_DPAA2_ETH
+       imply PTP_1588_CLOCK
+       default y
        help
          This driver adds support for using the DPAA2 1588 timer module
          as a PTP clock.
index ae0f88b..697c242 100644 (file)
@@ -2098,6 +2098,7 @@ static int fec_enet_get_regs_len(struct net_device *ndev)
 #if defined(CONFIG_M523x) || defined(CONFIG_M527x) || defined(CONFIG_M528x) || \
        defined(CONFIG_M520x) || defined(CONFIG_M532x) || defined(CONFIG_ARM) || \
        defined(CONFIG_ARM64) || defined(CONFIG_COMPILE_TEST)
+static __u32 fec_enet_register_version = 2;
 static u32 fec_enet_register_offset[] = {
        FEC_IEVENT, FEC_IMASK, FEC_R_DES_ACTIVE_0, FEC_X_DES_ACTIVE_0,
        FEC_ECNTRL, FEC_MII_DATA, FEC_MII_SPEED, FEC_MIB_CTRLSTAT, FEC_R_CNTRL,
@@ -2128,6 +2129,7 @@ static u32 fec_enet_register_offset[] = {
        IEEE_R_FDXFC, IEEE_R_OCTETS_OK
 };
 #else
+static __u32 fec_enet_register_version = 1;
 static u32 fec_enet_register_offset[] = {
        FEC_ECNTRL, FEC_IEVENT, FEC_IMASK, FEC_IVEC, FEC_R_DES_ACTIVE_0,
        FEC_R_DES_ACTIVE_1, FEC_R_DES_ACTIVE_2, FEC_X_DES_ACTIVE_0,
@@ -2149,6 +2151,8 @@ static void fec_enet_get_regs(struct net_device *ndev,
        u32 *buf = (u32 *)regbuf;
        u32 i, off;
 
+       regs->version = fec_enet_register_version;
+
        memset(buf, 0, regs->len);
 
        for (i = 0; i < ARRAY_SIZE(fec_enet_register_offset); i++) {
@@ -3467,7 +3471,7 @@ fec_probe(struct platform_device *pdev)
        if (ret)
                goto failed_clk_ipg;
 
-       fep->reg_phy = devm_regulator_get(&pdev->dev, "phy");
+       fep->reg_phy = devm_regulator_get_optional(&pdev->dev, "phy");
        if (!IS_ERR(fep->reg_phy)) {
                ret = regulator_enable(fep->reg_phy);
                if (ret) {
index b90bab7..c1968b3 100644 (file)
@@ -369,7 +369,7 @@ static irqreturn_t mpc52xx_fec_tx_interrupt(int irq, void *dev_id)
                dma_unmap_single(dev->dev.parent, bd->skb_pa, skb->len,
                                 DMA_TO_DEVICE);
 
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
        }
        spin_unlock(&priv->lock);
 
index c3d539e..eb3e65e 100644 (file)
@@ -1879,6 +1879,8 @@ static void ucc_geth_free_tx(struct ucc_geth_private *ugeth)
        u16 i, j;
        u8 __iomem *bd;
 
+       netdev_reset_queue(ugeth->ndev);
+
        ug_info = ugeth->ug_info;
        uf_info = &ug_info->uf_info;
 
index 471805e..e5d853b 100644 (file)
@@ -1006,8 +1006,8 @@ static int hix5hd2_init_hw_desc_queue(struct hix5hd2_priv *priv)
 
        for (i = 0; i < QUEUE_NUMS; i++) {
                size = priv->pool[i].count * sizeof(struct hix5hd2_desc);
-               virt_addr = dma_zalloc_coherent(dev, size, &phys_addr,
-                                               GFP_KERNEL);
+               virt_addr = dma_alloc_coherent(dev, size, &phys_addr,
+                                              GFP_KERNEL);
                if (virt_addr == NULL)
                        goto error_free_pool;
 
index ad1779f..a78bfaf 100644 (file)
@@ -147,12 +147,10 @@ static void hns_ae_put_handle(struct hnae_handle *handle)
        struct hnae_vf_cb *vf_cb = hns_ae_get_vf_cb(handle);
        int i;
 
-       vf_cb->mac_cb    = NULL;
-
-       kfree(vf_cb);
-
        for (i = 0; i < handle->q_num; i++)
                hns_ae_get_ring_pair(handle->qs[i])->used_by_vf = 0;
+
+       kfree(vf_cb);
 }
 
 static int hns_ae_wait_flow_down(struct hnae_handle *handle)
index 3b9e74b..ac55db0 100644 (file)
@@ -3081,6 +3081,7 @@ int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset)
        dsaf_dev = dev_get_drvdata(&pdev->dev);
        if (!dsaf_dev) {
                dev_err(&pdev->dev, "dsaf_dev is NULL\n");
+               put_device(&pdev->dev);
                return -ENODEV;
        }
 
@@ -3088,6 +3089,7 @@ int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset)
        if (AE_IS_VER1(dsaf_dev->dsaf_ver)) {
                dev_err(dsaf_dev->dev, "%s v1 chip doesn't support RoCE!\n",
                        dsaf_dev->ae_dev.name);
+               put_device(&pdev->dev);
                return -ENODEV;
        }
 
@@ -3126,6 +3128,9 @@ int hns_dsaf_roce_reset(struct fwnode_handle *dsaf_fwnode, bool dereset)
                dsaf_set_bit(credit, DSAF_SBM_ROCEE_CFG_CRD_EN_B, 1);
                dsaf_write_dev(dsaf_dev, DSAF_SBM_ROCEE_CFG_REG_REG, credit);
        }
+
+       put_device(&pdev->dev);
+
        return 0;
 }
 EXPORT_SYMBOL(hns_dsaf_roce_reset);
index 5748d3f..60e7d7a 100644 (file)
@@ -1170,6 +1170,13 @@ int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h)
        if (!h->phy_dev)
                return 0;
 
+       ethtool_convert_legacy_u32_to_link_mode(supported, h->if_support);
+       linkmode_and(phy_dev->supported, phy_dev->supported, supported);
+       linkmode_copy(phy_dev->advertising, phy_dev->supported);
+
+       if (h->phy_if == PHY_INTERFACE_MODE_XGMII)
+               phy_dev->autoneg = false;
+
        if (h->phy_if != PHY_INTERFACE_MODE_XGMII) {
                phy_dev->dev_flags = 0;
 
@@ -1181,16 +1188,6 @@ int hns_nic_init_phy(struct net_device *ndev, struct hnae_handle *h)
        if (unlikely(ret))
                return -ENODEV;
 
-       ethtool_convert_legacy_u32_to_link_mode(supported, h->if_support);
-       linkmode_and(phy_dev->supported, phy_dev->supported, supported);
-       linkmode_copy(phy_dev->advertising, phy_dev->supported);
-
-       if (h->phy_if == PHY_INTERFACE_MODE_XGMII)
-               phy_dev->autoneg = false;
-
-       if (h->phy_if == PHY_INTERFACE_MODE_SGMII)
-               phy_stop(phy_dev);
-
        return 0;
 }
 
@@ -2421,6 +2418,8 @@ static int hns_nic_dev_probe(struct platform_device *pdev)
 out_notify_fail:
        (void)cancel_work_sync(&priv->service_task);
 out_read_prop_fail:
+       /* safe for ACPI FW */
+       of_node_put(to_of_node(priv->fwnode));
        free_netdev(ndev);
        return ret;
 }
@@ -2450,6 +2449,9 @@ static int hns_nic_dev_remove(struct platform_device *pdev)
        set_bit(NIC_STATE_REMOVING, &priv->state);
        (void)cancel_work_sync(&priv->service_task);
 
+       /* safe for ACPI FW */
+       of_node_put(to_of_node(priv->fwnode));
+
        free_netdev(ndev);
        return 0;
 }
index 8e9b958..ce15d23 100644 (file)
@@ -1157,16 +1157,18 @@ static int hns_get_regs_len(struct net_device *net_dev)
  */
 static int hns_nic_nway_reset(struct net_device *netdev)
 {
-       int ret = 0;
        struct phy_device *phy = netdev->phydev;
 
-       if (netif_running(netdev)) {
-               /* if autoneg is disabled, don't restart auto-negotiation */
-               if (phy && phy->autoneg == AUTONEG_ENABLE)
-                       ret = genphy_restart_aneg(phy);
-       }
+       if (!netif_running(netdev))
+               return 0;
 
-       return ret;
+       if (!phy)
+               return -EOPNOTSUPP;
+
+       if (phy->autoneg != AUTONEG_ENABLE)
+               return -EINVAL;
+
+       return genphy_restart_aneg(phy);
 }
 
 static u32
index 07cd587..1bf7a5f 100644 (file)
@@ -2041,9 +2041,8 @@ static int hns3_alloc_desc(struct hns3_enet_ring *ring)
 {
        int size = ring->desc_num * sizeof(ring->desc[0]);
 
-       ring->desc = dma_zalloc_coherent(ring_to_dev(ring), size,
-                                        &ring->desc_dma_addr,
-                                        GFP_KERNEL);
+       ring->desc = dma_alloc_coherent(ring_to_dev(ring), size,
+                                       &ring->desc_dma_addr, GFP_KERNEL);
        if (!ring->desc)
                return -ENOMEM;
 
index 8af0cef..e483a6e 100644 (file)
@@ -39,9 +39,8 @@ static int hclge_alloc_cmd_desc(struct hclge_cmq_ring *ring)
 {
        int size  = ring->desc_num * sizeof(struct hclge_desc);
 
-       ring->desc = dma_zalloc_coherent(cmq_ring_to_dev(ring),
-                                        size, &ring->desc_dma_addr,
-                                        GFP_KERNEL);
+       ring->desc = dma_alloc_coherent(cmq_ring_to_dev(ring), size,
+                                       &ring->desc_dma_addr, GFP_KERNEL);
        if (!ring->desc)
                return -ENOMEM;
 
index d5765c8..4e78e88 100644 (file)
@@ -115,9 +115,8 @@ static int hclgevf_alloc_cmd_desc(struct hclgevf_cmq_ring *ring)
 {
        int size = ring->desc_num * sizeof(struct hclgevf_desc);
 
-       ring->desc = dma_zalloc_coherent(cmq_ring_to_dev(ring),
-                                        size, &ring->desc_dma_addr,
-                                        GFP_KERNEL);
+       ring->desc = dma_alloc_coherent(cmq_ring_to_dev(ring), size,
+                                       &ring->desc_dma_addr, GFP_KERNEL);
        if (!ring->desc)
                return -ENOMEM;
 
index 017e084..baf5cc2 100644 (file)
@@ -321,7 +321,7 @@ static int hns_mdio_read(struct mii_bus *bus, int phy_id, int regnum)
                }
 
                hns_mdio_cmd_write(mdio_dev, is_c45,
-                                  MDIO_C45_WRITE_ADDR, phy_id, devad);
+                                  MDIO_C45_READ, phy_id, devad);
        }
 
        /* Step 5: waitting for MDIO_COMMAND_REG 's mdio_start==0,*/
index c40603a..b4fefb4 100644 (file)
@@ -613,8 +613,8 @@ static int alloc_cmd_buf(struct hinic_api_cmd_chain *chain,
        u8 *cmd_vaddr;
        int err = 0;
 
-       cmd_vaddr = dma_zalloc_coherent(&pdev->dev, API_CMD_BUF_SIZE,
-                                       &cmd_paddr, GFP_KERNEL);
+       cmd_vaddr = dma_alloc_coherent(&pdev->dev, API_CMD_BUF_SIZE,
+                                      &cmd_paddr, GFP_KERNEL);
        if (!cmd_vaddr) {
                dev_err(&pdev->dev, "Failed to allocate API CMD DMA memory\n");
                return -ENOMEM;
@@ -663,8 +663,8 @@ static int api_cmd_create_cell(struct hinic_api_cmd_chain *chain,
        dma_addr_t node_paddr;
        int err;
 
-       node = dma_zalloc_coherent(&pdev->dev, chain->cell_size,
-                                  &node_paddr, GFP_KERNEL);
+       node = dma_alloc_coherent(&pdev->dev, chain->cell_size, &node_paddr,
+                                 GFP_KERNEL);
        if (!node) {
                dev_err(&pdev->dev, "Failed to allocate dma API CMD cell\n");
                return -ENOMEM;
@@ -821,10 +821,10 @@ static int api_chain_init(struct hinic_api_cmd_chain *chain,
        if (!chain->cell_ctxt)
                return -ENOMEM;
 
-       chain->wb_status = dma_zalloc_coherent(&pdev->dev,
-                                              sizeof(*chain->wb_status),
-                                              &chain->wb_status_paddr,
-                                              GFP_KERNEL);
+       chain->wb_status = dma_alloc_coherent(&pdev->dev,
+                                             sizeof(*chain->wb_status),
+                                             &chain->wb_status_paddr,
+                                             GFP_KERNEL);
        if (!chain->wb_status) {
                dev_err(&pdev->dev, "Failed to allocate DMA wb status\n");
                return -ENOMEM;
index 7cb8b9b..683e675 100644 (file)
@@ -593,10 +593,10 @@ static int alloc_eq_pages(struct hinic_eq *eq)
        }
 
        for (pg = 0; pg < eq->num_pages; pg++) {
-               eq->virt_addr[pg] = dma_zalloc_coherent(&pdev->dev,
-                                                       eq->page_size,
-                                                       &eq->dma_addr[pg],
-                                                       GFP_KERNEL);
+               eq->virt_addr[pg] = dma_alloc_coherent(&pdev->dev,
+                                                      eq->page_size,
+                                                      &eq->dma_addr[pg],
+                                                      GFP_KERNEL);
                if (!eq->virt_addr[pg]) {
                        err = -ENOMEM;
                        goto err_dma_alloc;
index 8e58976..a322a22 100644 (file)
@@ -355,9 +355,9 @@ int hinic_io_create_qps(struct hinic_func_to_io *func_to_io,
                goto err_sq_db;
        }
 
-       ci_addr_base = dma_zalloc_coherent(&pdev->dev, CI_TABLE_SIZE(num_qps),
-                                          &func_to_io->ci_dma_base,
-                                          GFP_KERNEL);
+       ci_addr_base = dma_alloc_coherent(&pdev->dev, CI_TABLE_SIZE(num_qps),
+                                         &func_to_io->ci_dma_base,
+                                         GFP_KERNEL);
        if (!ci_addr_base) {
                dev_err(&pdev->dev, "Failed to allocate CI area\n");
                err = -ENOMEM;
index bbf9bdd..d62cf50 100644 (file)
@@ -336,9 +336,9 @@ static int alloc_rq_cqe(struct hinic_rq *rq)
                goto err_cqe_dma_arr_alloc;
 
        for (i = 0; i < wq->q_depth; i++) {
-               rq->cqe[i] = dma_zalloc_coherent(&pdev->dev,
-                                                sizeof(*rq->cqe[i]),
-                                                &rq->cqe_dma[i], GFP_KERNEL);
+               rq->cqe[i] = dma_alloc_coherent(&pdev->dev,
+                                               sizeof(*rq->cqe[i]),
+                                               &rq->cqe_dma[i], GFP_KERNEL);
                if (!rq->cqe[i])
                        goto err_cqe_alloc;
        }
@@ -415,8 +415,8 @@ int hinic_init_rq(struct hinic_rq *rq, struct hinic_hwif *hwif,
 
        /* HW requirements: Must be at least 32 bit */
        pi_size = ALIGN(sizeof(*rq->pi_virt_addr), sizeof(u32));
-       rq->pi_virt_addr = dma_zalloc_coherent(&pdev->dev, pi_size,
-                                              &rq->pi_dma_addr, GFP_KERNEL);
+       rq->pi_virt_addr = dma_alloc_coherent(&pdev->dev, pi_size,
+                                             &rq->pi_dma_addr, GFP_KERNEL);
        if (!rq->pi_virt_addr) {
                dev_err(&pdev->dev, "Failed to allocate PI address\n");
                err = -ENOMEM;
index 1dfa7eb..cb66e70 100644 (file)
@@ -114,8 +114,8 @@ static int queue_alloc_page(struct hinic_hwif *hwif, u64 **vaddr, u64 *paddr,
        struct pci_dev *pdev = hwif->pdev;
        dma_addr_t dma_addr;
 
-       *vaddr = dma_zalloc_coherent(&pdev->dev, page_sz, &dma_addr,
-                                    GFP_KERNEL);
+       *vaddr = dma_alloc_coherent(&pdev->dev, page_sz, &dma_addr,
+                                   GFP_KERNEL);
        if (!*vaddr) {
                dev_err(&pdev->dev, "Failed to allocate dma for wqs page\n");
                return -ENOMEM;
@@ -482,8 +482,8 @@ static int alloc_wq_pages(struct hinic_wq *wq, struct hinic_hwif *hwif,
                u64 *paddr = &wq->block_vaddr[i];
                dma_addr_t dma_addr;
 
-               *vaddr = dma_zalloc_coherent(&pdev->dev, wq->wq_page_size,
-                                            &dma_addr, GFP_KERNEL);
+               *vaddr = dma_alloc_coherent(&pdev->dev, wq->wq_page_size,
+                                           &dma_addr, GFP_KERNEL);
                if (!*vaddr) {
                        dev_err(&pdev->dev, "Failed to allocate wq page\n");
                        goto err_alloc_wq_pages;
index d719668..9292975 100644 (file)
@@ -1310,7 +1310,7 @@ static irqreturn_t i596_interrupt(int irq, void *dev_id)
                                                dev->stats.tx_aborted_errors++;
                                }
 
-                               dev_kfree_skb_irq(skb);
+                               dev_consume_skb_irq(skb);
 
                                tx_cmd->cmd.command = 0; /* Mark free */
                                break;
index fff09dc..787d5ac 100644 (file)
@@ -636,8 +636,8 @@ static int mal_probe(struct platform_device *ofdev)
        bd_size = sizeof(struct mal_descriptor) *
                (NUM_TX_BUFF * mal->num_tx_chans +
                 NUM_RX_BUFF * mal->num_rx_chans);
-       mal->bd_virt = dma_zalloc_coherent(&ofdev->dev, bd_size, &mal->bd_dma,
-                                          GFP_KERNEL);
+       mal->bd_virt = dma_alloc_coherent(&ofdev->dev, bd_size, &mal->bd_dma,
+                                         GFP_KERNEL);
        if (mal->bd_virt == NULL) {
                err = -ENOMEM;
                goto fail_unmap;
index 098d876..dd71d5d 100644 (file)
@@ -1313,7 +1313,6 @@ static int ibmveth_poll(struct napi_struct *napi, int budget)
        unsigned long lpar_rc;
        u16 mss = 0;
 
-restart_poll:
        while (frames_processed < budget) {
                if (!ibmveth_rxq_pending_buffer(adapter))
                        break;
@@ -1401,7 +1400,6 @@ restart_poll:
                    napi_reschedule(napi)) {
                        lpar_rc = h_vio_signal(adapter->vdev->unit_address,
                                               VIO_IRQ_DISABLE);
-                       goto restart_poll;
                }
        }
 
index 31fb76e..a1246e8 100644 (file)
@@ -159,7 +159,7 @@ config IXGBE
        tristate "Intel(R) 10GbE PCI Express adapters support"
        depends on PCI
        select MDIO
-       select MDIO_DEVICE
+       select PHYLIB
        imply PTP_1588_CLOCK
        ---help---
          This driver supports Intel(R) 10GbE PCI Express family of
index 2569a16..a410085 100644 (file)
@@ -993,8 +993,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
 
        txdr->size = txdr->count * sizeof(struct e1000_tx_desc);
        txdr->size = ALIGN(txdr->size, 4096);
-       txdr->desc = dma_zalloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
-                                        GFP_KERNEL);
+       txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
+                                       GFP_KERNEL);
        if (!txdr->desc) {
                ret_val = 2;
                goto err_nomem;
@@ -1051,8 +1051,8 @@ static int e1000_setup_desc_rings(struct e1000_adapter *adapter)
        }
 
        rxdr->size = rxdr->count * sizeof(struct e1000_rx_desc);
-       rxdr->desc = dma_zalloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
-                                        GFP_KERNEL);
+       rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
+                                       GFP_KERNEL);
        if (!rxdr->desc) {
                ret_val = 6;
                goto err_nomem;
index 308c006..189f231 100644 (file)
@@ -2305,8 +2305,8 @@ static int e1000_alloc_ring_dma(struct e1000_adapter *adapter,
 {
        struct pci_dev *pdev = adapter->pdev;
 
-       ring->desc = dma_zalloc_coherent(&pdev->dev, ring->size, &ring->dma,
-                                        GFP_KERNEL);
+       ring->desc = dma_alloc_coherent(&pdev->dev, ring->size, &ring->dma,
+                                       GFP_KERNEL);
        if (!ring->desc)
                return -ENOMEM;
 
index 4d40878..e4ff531 100644 (file)
@@ -109,8 +109,8 @@ int i40e_allocate_dma_mem_d(struct i40e_hw *hw, struct i40e_dma_mem *mem,
        struct i40e_pf *pf = (struct i40e_pf *)hw->back;
 
        mem->size = ALIGN(size, alignment);
-       mem->va = dma_zalloc_coherent(&pf->pdev->dev, mem->size,
-                                     &mem->pa, GFP_KERNEL);
+       mem->va = dma_alloc_coherent(&pf->pdev->dev, mem->size, &mem->pa,
+                                    GFP_KERNEL);
        if (!mem->va)
                return -ENOMEM;
 
@@ -3289,8 +3289,11 @@ static int i40e_configure_rx_ring(struct i40e_ring *ring)
             i40e_alloc_rx_buffers_zc(ring, I40E_DESC_UNUSED(ring)) :
             !i40e_alloc_rx_buffers(ring, I40E_DESC_UNUSED(ring));
        if (!ok) {
+               /* Log this in case the user has forgotten to give the kernel
+                * any buffers, even later in the application.
+                */
                dev_info(&vsi->back->pdev->dev,
-                        "Failed allocate some buffers on %sRx ring %d (pf_q %d)\n",
+                        "Failed to allocate some buffers on %sRx ring %d (pf_q %d)\n",
                         ring->xsk_umem ? "UMEM enabled " : "",
                         ring->queue_index, pf_q);
        }
@@ -6725,8 +6728,13 @@ void i40e_down(struct i40e_vsi *vsi)
 
        for (i = 0; i < vsi->num_queue_pairs; i++) {
                i40e_clean_tx_ring(vsi->tx_rings[i]);
-               if (i40e_enabled_xdp_vsi(vsi))
+               if (i40e_enabled_xdp_vsi(vsi)) {
+                       /* Make sure that in-progress ndo_xdp_xmit
+                        * calls are completed.
+                        */
+                       synchronize_rcu();
                        i40e_clean_tx_ring(vsi->xdp_rings[i]);
+               }
                i40e_clean_rx_ring(vsi->rx_rings[i]);
        }
 
@@ -11895,6 +11903,14 @@ static int i40e_xdp_setup(struct i40e_vsi *vsi,
        if (old_prog)
                bpf_prog_put(old_prog);
 
+       /* Kick start the NAPI context if there is an AF_XDP socket open
+        * on that queue id. This so that receiving will start.
+        */
+       if (need_reset && prog)
+               for (i = 0; i < vsi->num_queue_pairs; i++)
+                       if (vsi->xdp_rings[i]->xsk_umem)
+                               (void)i40e_xsk_async_xmit(vsi->netdev, i);
+
        return 0;
 }
 
@@ -11955,8 +11971,13 @@ static void i40e_queue_pair_reset_stats(struct i40e_vsi *vsi, int queue_pair)
 static void i40e_queue_pair_clean_rings(struct i40e_vsi *vsi, int queue_pair)
 {
        i40e_clean_tx_ring(vsi->tx_rings[queue_pair]);
-       if (i40e_enabled_xdp_vsi(vsi))
+       if (i40e_enabled_xdp_vsi(vsi)) {
+               /* Make sure that in-progress ndo_xdp_xmit calls are
+                * completed.
+                */
+               synchronize_rcu();
                i40e_clean_tx_ring(vsi->xdp_rings[queue_pair]);
+       }
        i40e_clean_rx_ring(vsi->rx_rings[queue_pair]);
 }
 
index a7e14e9..6c97667 100644 (file)
@@ -3709,6 +3709,7 @@ int i40e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
        struct i40e_netdev_priv *np = netdev_priv(dev);
        unsigned int queue_index = smp_processor_id();
        struct i40e_vsi *vsi = np->vsi;
+       struct i40e_pf *pf = vsi->back;
        struct i40e_ring *xdp_ring;
        int drops = 0;
        int i;
@@ -3716,7 +3717,8 @@ int i40e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
        if (test_bit(__I40E_VSI_DOWN, vsi->state))
                return -ENETDOWN;
 
-       if (!i40e_enabled_xdp_vsi(vsi) || queue_index >= vsi->num_queue_pairs)
+       if (!i40e_enabled_xdp_vsi(vsi) || queue_index >= vsi->num_queue_pairs ||
+           test_bit(__I40E_CONFIG_BUSY, pf->state))
                return -ENXIO;
 
        if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
index 870cf65..3827f16 100644 (file)
@@ -183,6 +183,11 @@ static int i40e_xsk_umem_enable(struct i40e_vsi *vsi, struct xdp_umem *umem,
                err = i40e_queue_pair_enable(vsi, qid);
                if (err)
                        return err;
+
+               /* Kick start the NAPI context so that receiving will start */
+               err = i40e_xsk_async_xmit(vsi->netdev, qid);
+               if (err)
+                       return err;
        }
 
        return 0;
index fe1592a..ca54e26 100644 (file)
@@ -515,7 +515,7 @@ struct igb_adapter {
        /* OS defined structs */
        struct pci_dev *pdev;
 
-       struct mutex stats64_lock;
+       spinlock_t stats64_lock;
        struct rtnl_link_stats64 stats64;
 
        /* structs defined in e1000_hw.h */
index 7426060..c576710 100644 (file)
@@ -2295,7 +2295,7 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
        int i, j;
        char *p;
 
-       mutex_lock(&adapter->stats64_lock);
+       spin_lock(&adapter->stats64_lock);
        igb_update_stats(adapter);
 
        for (i = 0; i < IGB_GLOBAL_STATS_LEN; i++) {
@@ -2338,7 +2338,7 @@ static void igb_get_ethtool_stats(struct net_device *netdev,
                } while (u64_stats_fetch_retry_irq(&ring->rx_syncp, start));
                i += IGB_RX_QUEUE_STATS_LEN;
        }
-       mutex_unlock(&adapter->stats64_lock);
+       spin_unlock(&adapter->stats64_lock);
 }
 
 static void igb_get_strings(struct net_device *netdev, u32 stringset, u8 *data)
index 87bdf16..7137e7f 100644 (file)
@@ -2203,9 +2203,9 @@ void igb_down(struct igb_adapter *adapter)
        del_timer_sync(&adapter->phy_info_timer);
 
        /* record the stats before reset*/
-       mutex_lock(&adapter->stats64_lock);
+       spin_lock(&adapter->stats64_lock);
        igb_update_stats(adapter);
-       mutex_unlock(&adapter->stats64_lock);
+       spin_unlock(&adapter->stats64_lock);
 
        adapter->link_speed = 0;
        adapter->link_duplex = 0;
@@ -3840,7 +3840,7 @@ static int igb_sw_init(struct igb_adapter *adapter)
        adapter->min_frame_size = ETH_ZLEN + ETH_FCS_LEN;
 
        spin_lock_init(&adapter->nfc_lock);
-       mutex_init(&adapter->stats64_lock);
+       spin_lock_init(&adapter->stats64_lock);
 #ifdef CONFIG_PCI_IOV
        switch (hw->mac.type) {
        case e1000_82576:
@@ -5406,9 +5406,9 @@ no_wait:
                }
        }
 
-       mutex_lock(&adapter->stats64_lock);
+       spin_lock(&adapter->stats64_lock);
        igb_update_stats(adapter);
-       mutex_unlock(&adapter->stats64_lock);
+       spin_unlock(&adapter->stats64_lock);
 
        for (i = 0; i < adapter->num_tx_queues; i++) {
                struct igb_ring *tx_ring = adapter->tx_ring[i];
@@ -6235,10 +6235,10 @@ static void igb_get_stats64(struct net_device *netdev,
 {
        struct igb_adapter *adapter = netdev_priv(netdev);
 
-       mutex_lock(&adapter->stats64_lock);
+       spin_lock(&adapter->stats64_lock);
        igb_update_stats(adapter);
        memcpy(stats, &adapter->stats64, sizeof(*stats));
-       mutex_unlock(&adapter->stats64_lock);
+       spin_unlock(&adapter->stats64_lock);
 }
 
 /**
index 1d4d168..e5ac2d3 100644 (file)
@@ -680,8 +680,8 @@ ixgb_setup_tx_resources(struct ixgb_adapter *adapter)
        txdr->size = txdr->count * sizeof(struct ixgb_tx_desc);
        txdr->size = ALIGN(txdr->size, 4096);
 
-       txdr->desc = dma_zalloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
-                                        GFP_KERNEL);
+       txdr->desc = dma_alloc_coherent(&pdev->dev, txdr->size, &txdr->dma,
+                                       GFP_KERNEL);
        if (!txdr->desc) {
                vfree(txdr->buffer_info);
                return -ENOMEM;
@@ -763,8 +763,8 @@ ixgb_setup_rx_resources(struct ixgb_adapter *adapter)
        rxdr->size = rxdr->count * sizeof(struct ixgb_rx_desc);
        rxdr->size = ALIGN(rxdr->size, 4096);
 
-       rxdr->desc = dma_zalloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
-                                        GFP_KERNEL);
+       rxdr->desc = dma_alloc_coherent(&pdev->dev, rxdr->size, &rxdr->dma,
+                                       GFP_KERNEL);
 
        if (!rxdr->desc) {
                vfree(rxdr->buffer_info);
index daff818..cb35d82 100644 (file)
@@ -3953,8 +3953,11 @@ static void ixgbe_setup_mrqc(struct ixgbe_adapter *adapter)
                        else
                                mrqc = IXGBE_MRQC_VMDQRSS64EN;
 
-                       /* Enable L3/L4 for Tx Switched packets */
-                       mrqc |= IXGBE_MRQC_L3L4TXSWEN;
+                       /* Enable L3/L4 for Tx Switched packets only for X550,
+                        * older devices do not support this feature
+                        */
+                       if (hw->mac.type >= ixgbe_mac_X550)
+                               mrqc |= IXGBE_MRQC_L3L4TXSWEN;
                } else {
                        if (tcs > 4)
                                mrqc = IXGBE_MRQC_RTRSS8TCEN;
@@ -10225,6 +10228,7 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
        int i, frame_size = dev->mtu + ETH_HLEN + ETH_FCS_LEN + VLAN_HLEN;
        struct ixgbe_adapter *adapter = netdev_priv(dev);
        struct bpf_prog *old_prog;
+       bool need_reset;
 
        if (adapter->flags & IXGBE_FLAG_SRIOV_ENABLED)
                return -EINVAL;
@@ -10247,9 +10251,10 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
                return -ENOMEM;
 
        old_prog = xchg(&adapter->xdp_prog, prog);
+       need_reset = (!!prog != !!old_prog);
 
        /* If transitioning XDP modes reconfigure rings */
-       if (!!prog != !!old_prog) {
+       if (need_reset) {
                int err = ixgbe_setup_tc(dev, adapter->hw_tcs);
 
                if (err) {
@@ -10265,6 +10270,14 @@ static int ixgbe_xdp_setup(struct net_device *dev, struct bpf_prog *prog)
        if (old_prog)
                bpf_prog_put(old_prog);
 
+       /* Kick start the NAPI context if there is an AF_XDP socket open
+        * on that queue id. This so that receiving will start.
+        */
+       if (need_reset && prog)
+               for (i = 0; i < adapter->num_rx_queues; i++)
+                       if (adapter->xdp_ring[i]->xsk_umem)
+                               (void)ixgbe_xsk_async_xmit(adapter->netdev, i);
+
        return 0;
 }
 
index 65c3e2c..36a8879 100644 (file)
@@ -144,11 +144,19 @@ static int ixgbe_xsk_umem_enable(struct ixgbe_adapter *adapter,
                ixgbe_txrx_ring_disable(adapter, qid);
 
        err = ixgbe_add_xsk_umem(adapter, umem, qid);
+       if (err)
+               return err;
 
-       if (if_running)
+       if (if_running) {
                ixgbe_txrx_ring_enable(adapter, qid);
 
-       return err;
+               /* Kick start the NAPI context so that receiving will start */
+               err = ixgbe_xsk_async_xmit(adapter->netdev, qid);
+               if (err)
+                       return err;
+       }
+
+       return 0;
 }
 
 static int ixgbe_xsk_umem_disable(struct ixgbe_adapter *adapter, u16 qid)
@@ -634,7 +642,8 @@ static bool ixgbe_xmit_zc(struct ixgbe_ring *xdp_ring, unsigned int budget)
        dma_addr_t dma;
 
        while (budget-- > 0) {
-               if (unlikely(!ixgbe_desc_unused(xdp_ring))) {
+               if (unlikely(!ixgbe_desc_unused(xdp_ring)) ||
+                   !netif_carrier_ok(xdp_ring->netdev)) {
                        work_done = false;
                        break;
                }
index 2f42727..292a668 100644 (file)
@@ -2879,7 +2879,7 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
 
        ret = mv643xx_eth_shared_of_probe(pdev);
        if (ret)
-               return ret;
+               goto err_put_clk;
        pd = dev_get_platdata(&pdev->dev);
 
        msp->tx_csum_limit = (pd != NULL && pd->tx_csum_limit) ?
@@ -2887,6 +2887,11 @@ static int mv643xx_eth_shared_probe(struct platform_device *pdev)
        infer_hw_params(msp);
 
        return 0;
+
+err_put_clk:
+       if (!IS_ERR(msp->clk))
+               clk_disable_unprepare(msp->clk);
+       return ret;
 }
 
 static int mv643xx_eth_shared_remove(struct platform_device *pdev)
index 9d4568e..8433fb9 100644 (file)
@@ -2146,7 +2146,7 @@ err_drop_frame:
                        if (unlikely(!skb))
                                goto err_drop_frame_ret_pool;
 
-                       dma_sync_single_range_for_cpu(dev->dev.parent,
+                       dma_sync_single_range_for_cpu(&pp->bm_priv->pdev->dev,
                                                      rx_desc->buf_phys_addr,
                                                      MVNETA_MH_SIZE + NET_SKB_PAD,
                                                      rx_bytes,
index e087547..16066c2 100644 (file)
@@ -2044,9 +2044,9 @@ static int mvpp2_aggr_txq_init(struct platform_device *pdev,
        u32 txq_dma;
 
        /* Allocate memory for TX descriptors */
-       aggr_txq->descs = dma_zalloc_coherent(&pdev->dev,
-                               MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE,
-                               &aggr_txq->descs_dma, GFP_KERNEL);
+       aggr_txq->descs = dma_alloc_coherent(&pdev->dev,
+                                            MVPP2_AGGR_TXQ_SIZE * MVPP2_DESC_ALIGNED_SIZE,
+                                            &aggr_txq->descs_dma, GFP_KERNEL);
        if (!aggr_txq->descs)
                return -ENOMEM;
 
index 742f0c1..6d55e3d 100644 (file)
@@ -825,7 +825,7 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (!cgx->cgx_cmd_workq) {
                dev_err(dev, "alloc workqueue failed for cgx cmd");
                err = -ENOMEM;
-               goto err_release_regions;
+               goto err_free_irq_vectors;
        }
 
        list_add(&cgx->cgx_list, &cgx_list);
@@ -841,6 +841,8 @@ static int cgx_probe(struct pci_dev *pdev, const struct pci_device_id *id)
 err_release_lmac:
        cgx_lmac_exit(cgx);
        list_del(&cgx->cgx_list);
+err_free_irq_vectors:
+       pci_free_irq_vectors(pdev);
 err_release_regions:
        pci_release_regions(pdev);
 err_disable_device:
index ec50a21..e332e82 100644 (file)
@@ -64,7 +64,7 @@ static inline int qmem_alloc(struct device *dev, struct qmem **q,
 
        qmem->entry_sz = entry_sz;
        qmem->alloc_sz = (qsize * entry_sz) + OTX2_ALIGN;
-       qmem->base = dma_zalloc_coherent(dev, qmem->alloc_sz,
+       qmem->base = dma_alloc_coherent(dev, qmem->alloc_sz,
                                         &qmem->iova, GFP_KERNEL);
        if (!qmem->base)
                return -ENOMEM;
index 0bd4351..f8a6d6e 100644 (file)
@@ -557,9 +557,9 @@ static int init_hash_table(struct pxa168_eth_private *pep)
         * table is full.
         */
        if (!pep->htpr) {
-               pep->htpr = dma_zalloc_coherent(pep->dev->dev.parent,
-                                               HASH_ADDR_TABLE_SIZE,
-                                               &pep->htpr_dma, GFP_KERNEL);
+               pep->htpr = dma_alloc_coherent(pep->dev->dev.parent,
+                                              HASH_ADDR_TABLE_SIZE,
+                                              &pep->htpr_dma, GFP_KERNEL);
                if (!pep->htpr)
                        return -ENOMEM;
        } else {
@@ -1044,9 +1044,9 @@ static int rxq_init(struct net_device *dev)
        pep->rx_desc_count = 0;
        size = pep->rx_ring_size * sizeof(struct rx_desc);
        pep->rx_desc_area_size = size;
-       pep->p_rx_desc_area = dma_zalloc_coherent(pep->dev->dev.parent, size,
-                                                 &pep->rx_desc_dma,
-                                                 GFP_KERNEL);
+       pep->p_rx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size,
+                                                &pep->rx_desc_dma,
+                                                GFP_KERNEL);
        if (!pep->p_rx_desc_area)
                goto out;
 
@@ -1103,9 +1103,9 @@ static int txq_init(struct net_device *dev)
        pep->tx_desc_count = 0;
        size = pep->tx_ring_size * sizeof(struct tx_desc);
        pep->tx_desc_area_size = size;
-       pep->p_tx_desc_area = dma_zalloc_coherent(pep->dev->dev.parent, size,
-                                                 &pep->tx_desc_dma,
-                                                 GFP_KERNEL);
+       pep->p_tx_desc_area = dma_alloc_coherent(pep->dev->dev.parent, size,
+                                                &pep->tx_desc_dma,
+                                                GFP_KERNEL);
        if (!pep->p_tx_desc_area)
                goto out;
        /* Initialize the next_desc_ptr links in the Tx descriptors ring */
index 04fd1f1..654ac53 100644 (file)
@@ -152,8 +152,10 @@ static void skge_get_regs(struct net_device *dev, struct ethtool_regs *regs,
        memset(p, 0, regs->len);
        memcpy_fromio(p, io, B3_RAM_ADDR);
 
-       memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
-                     regs->len - B3_RI_WTO_R1);
+       if (regs->len > B3_RI_WTO_R1) {
+               memcpy_fromio(p + B3_RI_WTO_R1, io + B3_RI_WTO_R1,
+                             regs->len - B3_RI_WTO_R1);
+       }
 }
 
 /* Wake on Lan only supported on Yukon chips with rev 1 or above */
index f3a5fa8..57727fe 100644 (file)
@@ -5073,7 +5073,7 @@ static int sky2_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
        INIT_WORK(&hw->restart_work, sky2_restart);
 
        pci_set_drvdata(pdev, hw);
-       pdev->d3_delay = 200;
+       pdev->d3_delay = 300;
 
        return 0;
 
index 399f565..49f926b 100644 (file)
@@ -258,11 +258,6 @@ static void mtk_phy_link_adjust(struct net_device *dev)
 
        mtk_w32(mac->hw, mcr, MTK_MAC_MCR(mac->id));
 
-       if (dev->phydev->link)
-               netif_carrier_on(dev);
-       else
-               netif_carrier_off(dev);
-
        if (!of_phy_is_fixed_link(mac->of_node))
                phy_print_status(dev->phydev);
 }
@@ -347,17 +342,6 @@ static int mtk_phy_connect(struct net_device *dev)
        if (mtk_phy_connect_node(eth, mac, np))
                goto err_phy;
 
-       dev->phydev->autoneg = AUTONEG_ENABLE;
-       dev->phydev->speed = 0;
-       dev->phydev->duplex = 0;
-
-       phy_set_max_speed(dev->phydev, SPEED_1000);
-       phy_support_asym_pause(dev->phydev);
-       linkmode_copy(dev->phydev->advertising, dev->phydev->supported);
-       linkmode_set_bit(ETHTOOL_LINK_MODE_Autoneg_BIT,
-                        dev->phydev->advertising);
-       phy_start_aneg(dev->phydev);
-
        of_node_put(np);
 
        return 0;
@@ -598,10 +582,10 @@ static int mtk_init_fq_dma(struct mtk_eth *eth)
        dma_addr_t dma_addr;
        int i;
 
-       eth->scratch_ring = dma_zalloc_coherent(eth->dev,
-                                               cnt * sizeof(struct mtk_tx_dma),
-                                               &eth->phy_scratch_ring,
-                                               GFP_ATOMIC);
+       eth->scratch_ring = dma_alloc_coherent(eth->dev,
+                                              cnt * sizeof(struct mtk_tx_dma),
+                                              &eth->phy_scratch_ring,
+                                              GFP_ATOMIC);
        if (unlikely(!eth->scratch_ring))
                return -ENOMEM;
 
@@ -1213,8 +1197,8 @@ static int mtk_tx_alloc(struct mtk_eth *eth)
        if (!ring->buf)
                goto no_tx_mem;
 
-       ring->dma = dma_zalloc_coherent(eth->dev, MTK_DMA_SIZE * sz,
-                                       &ring->phys, GFP_ATOMIC);
+       ring->dma = dma_alloc_coherent(eth->dev, MTK_DMA_SIZE * sz,
+                                      &ring->phys, GFP_ATOMIC);
        if (!ring->dma)
                goto no_tx_mem;
 
@@ -1310,9 +1294,9 @@ static int mtk_rx_alloc(struct mtk_eth *eth, int ring_no, int rx_flag)
                        return -ENOMEM;
        }
 
-       ring->dma = dma_zalloc_coherent(eth->dev,
-                                       rx_dma_size * sizeof(*ring->dma),
-                                       &ring->phys, GFP_ATOMIC);
+       ring->dma = dma_alloc_coherent(eth->dev,
+                                      rx_dma_size * sizeof(*ring->dma),
+                                      &ring->phys, GFP_ATOMIC);
        if (!ring->dma)
                return -ENOMEM;
 
index 9af34e0..dbc483e 100644 (file)
@@ -584,8 +584,8 @@ static int mlx4_buf_direct_alloc(struct mlx4_dev *dev, int size,
        buf->npages       = 1;
        buf->page_shift   = get_order(size) + PAGE_SHIFT;
        buf->direct.buf   =
-               dma_zalloc_coherent(&dev->persist->pdev->dev,
-                                   size, &t, GFP_KERNEL);
+               dma_alloc_coherent(&dev->persist->pdev->dev, size, &t,
+                                  GFP_KERNEL);
        if (!buf->direct.buf)
                return -ENOMEM;
 
@@ -624,8 +624,8 @@ int mlx4_buf_alloc(struct mlx4_dev *dev, int size, int max_direct,
 
                for (i = 0; i < buf->nbufs; ++i) {
                        buf->page_list[i].buf =
-                               dma_zalloc_coherent(&dev->persist->pdev->dev,
-                                                   PAGE_SIZE, &t, GFP_KERNEL);
+                               dma_alloc_coherent(&dev->persist->pdev->dev,
+                                                  PAGE_SIZE, &t, GFP_KERNEL);
                        if (!buf->page_list[i].buf)
                                goto err_free;
 
index db909b6..65f8a4b 100644 (file)
@@ -306,14 +306,16 @@ static int mlx4_init_user_cqes(void *buf, int entries, int cqe_size)
 
        if (entries_per_copy < entries) {
                for (i = 0; i < entries / entries_per_copy; i++) {
-                       err = copy_to_user(buf, init_ents, PAGE_SIZE);
+                       err = copy_to_user((void __user *)buf, init_ents, PAGE_SIZE) ?
+                               -EFAULT : 0;
                        if (err)
                                goto out;
 
                        buf += PAGE_SIZE;
                }
        } else {
-               err = copy_to_user(buf, init_ents, entries * cqe_size);
+               err = copy_to_user((void __user *)buf, init_ents, entries * cqe_size) ?
+                       -EFAULT : 0;
        }
 
 out:
index 6b88881..c1438ae 100644 (file)
@@ -3360,7 +3360,7 @@ int mlx4_en_init_netdev(struct mlx4_en_dev *mdev, int port,
        dev->addr_len = ETH_ALEN;
        mlx4_en_u64_to_mac(dev->dev_addr, mdev->dev->caps.def_mac[priv->port]);
        if (!is_valid_ether_addr(dev->dev_addr)) {
-               en_err(priv, "Port: %d, invalid mac burned: %pM, quiting\n",
+               en_err(priv, "Port: %d, invalid mac burned: %pM, quitting\n",
                       priv->port, dev->dev_addr);
                err = -EINVAL;
                goto out;
index 9a0881c..6c01314 100644 (file)
@@ -617,6 +617,8 @@ static int get_fixed_ipv6_csum(__wsum hw_checksum, struct sk_buff *skb,
 }
 #endif
 
+#define short_frame(size) ((size) <= ETH_ZLEN + ETH_FCS_LEN)
+
 /* We reach this function only after checking that any of
  * the (IPv4 | IPv6) bits are set in cqe->status.
  */
@@ -624,9 +626,20 @@ static int check_csum(struct mlx4_cqe *cqe, struct sk_buff *skb, void *va,
                      netdev_features_t dev_features)
 {
        __wsum hw_checksum = 0;
+       void *hdr;
+
+       /* CQE csum doesn't cover padding octets in short ethernet
+        * frames. And the pad field is appended prior to calculating
+        * and appending the FCS field.
+        *
+        * Detecting these padded frames requires to verify and parse
+        * IP headers, so we simply force all those small frames to skip
+        * checksum complete.
+        */
+       if (short_frame(skb->len))
+               return -EINVAL;
 
-       void *hdr = (u8 *)va + sizeof(struct ethhdr);
-
+       hdr = (u8 *)va + sizeof(struct ethhdr);
        hw_checksum = csum_unfold((__force __sum16)cqe->checksum);
 
        if (cqe->vlan_my_qpn & cpu_to_be32(MLX4_CQE_CVLAN_PRESENT_MASK) &&
@@ -819,6 +832,11 @@ xdp_drop_no_cnt:
                skb_record_rx_queue(skb, cq_ring);
 
                if (likely(dev->features & NETIF_F_RXCSUM)) {
+                       /* TODO: For IP non TCP/UDP packets when csum complete is
+                        * not an option (not supported or any other reason) we can
+                        * actually check cqe IPOK status bit and report
+                        * CHECKSUM_UNNECESSARY rather than CHECKSUM_NONE
+                        */
                        if ((cqe->status & cpu_to_be16(MLX4_CQE_STATUS_TCP |
                                                       MLX4_CQE_STATUS_UDP)) &&
                            (cqe->status & cpu_to_be16(MLX4_CQE_STATUS_IPOK)) &&
index 7df728f..6e501af 100644 (file)
@@ -2067,9 +2067,11 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 {
        struct mlx4_cmd_mailbox *mailbox;
        __be32 *outbox;
+       u64 qword_field;
        u32 dword_field;
-       int err;
+       u16 word_field;
        u8 byte_field;
+       int err;
        static const u8 a0_dmfs_query_hw_steering[] =  {
                [0] = MLX4_STEERING_DMFS_A0_DEFAULT,
                [1] = MLX4_STEERING_DMFS_A0_DYNAMIC,
@@ -2097,19 +2099,32 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
 
        /* QPC/EEC/CQC/EQC/RDMARC attributes */
 
-       MLX4_GET(param->qpc_base,      outbox, INIT_HCA_QPC_BASE_OFFSET);
-       MLX4_GET(param->log_num_qps,   outbox, INIT_HCA_LOG_QP_OFFSET);
-       MLX4_GET(param->srqc_base,     outbox, INIT_HCA_SRQC_BASE_OFFSET);
-       MLX4_GET(param->log_num_srqs,  outbox, INIT_HCA_LOG_SRQ_OFFSET);
-       MLX4_GET(param->cqc_base,      outbox, INIT_HCA_CQC_BASE_OFFSET);
-       MLX4_GET(param->log_num_cqs,   outbox, INIT_HCA_LOG_CQ_OFFSET);
-       MLX4_GET(param->altc_base,     outbox, INIT_HCA_ALTC_BASE_OFFSET);
-       MLX4_GET(param->auxc_base,     outbox, INIT_HCA_AUXC_BASE_OFFSET);
-       MLX4_GET(param->eqc_base,      outbox, INIT_HCA_EQC_BASE_OFFSET);
-       MLX4_GET(param->log_num_eqs,   outbox, INIT_HCA_LOG_EQ_OFFSET);
-       MLX4_GET(param->num_sys_eqs,   outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
-       MLX4_GET(param->rdmarc_base,   outbox, INIT_HCA_RDMARC_BASE_OFFSET);
-       MLX4_GET(param->log_rd_per_qp, outbox, INIT_HCA_LOG_RD_OFFSET);
+       MLX4_GET(qword_field, outbox, INIT_HCA_QPC_BASE_OFFSET);
+       param->qpc_base = qword_field & ~((u64)0x1f);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_QP_OFFSET);
+       param->log_num_qps = byte_field & 0x1f;
+       MLX4_GET(qword_field, outbox, INIT_HCA_SRQC_BASE_OFFSET);
+       param->srqc_base = qword_field & ~((u64)0x1f);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_SRQ_OFFSET);
+       param->log_num_srqs = byte_field & 0x1f;
+       MLX4_GET(qword_field, outbox, INIT_HCA_CQC_BASE_OFFSET);
+       param->cqc_base = qword_field & ~((u64)0x1f);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_CQ_OFFSET);
+       param->log_num_cqs = byte_field & 0x1f;
+       MLX4_GET(qword_field, outbox, INIT_HCA_ALTC_BASE_OFFSET);
+       param->altc_base = qword_field;
+       MLX4_GET(qword_field, outbox, INIT_HCA_AUXC_BASE_OFFSET);
+       param->auxc_base = qword_field;
+       MLX4_GET(qword_field, outbox, INIT_HCA_EQC_BASE_OFFSET);
+       param->eqc_base = qword_field & ~((u64)0x1f);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_EQ_OFFSET);
+       param->log_num_eqs = byte_field & 0x1f;
+       MLX4_GET(word_field, outbox, INIT_HCA_NUM_SYS_EQS_OFFSET);
+       param->num_sys_eqs = word_field & 0xfff;
+       MLX4_GET(qword_field, outbox, INIT_HCA_RDMARC_BASE_OFFSET);
+       param->rdmarc_base = qword_field & ~((u64)0x1f);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_RD_OFFSET);
+       param->log_rd_per_qp = byte_field & 0x7;
 
        MLX4_GET(dword_field, outbox, INIT_HCA_FLAGS_OFFSET);
        if (dword_field & (1 << INIT_HCA_DEVICE_MANAGED_FLOW_STEERING_EN)) {
@@ -2128,22 +2143,21 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
        /* steering attributes */
        if (param->steering_mode == MLX4_STEERING_MODE_DEVICE_MANAGED) {
                MLX4_GET(param->mc_base, outbox, INIT_HCA_FS_BASE_OFFSET);
-               MLX4_GET(param->log_mc_entry_sz, outbox,
-                        INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
-               MLX4_GET(param->log_mc_table_sz, outbox,
-                        INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
-               MLX4_GET(byte_field, outbox,
-                        INIT_HCA_FS_A0_OFFSET);
+               MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_ENTRY_SZ_OFFSET);
+               param->log_mc_entry_sz = byte_field & 0x1f;
+               MLX4_GET(byte_field, outbox, INIT_HCA_FS_LOG_TABLE_SZ_OFFSET);
+               param->log_mc_table_sz = byte_field & 0x1f;
+               MLX4_GET(byte_field, outbox, INIT_HCA_FS_A0_OFFSET);
                param->dmfs_high_steer_mode =
                        a0_dmfs_query_hw_steering[(byte_field >> 6) & 3];
        } else {
                MLX4_GET(param->mc_base, outbox, INIT_HCA_MC_BASE_OFFSET);
-               MLX4_GET(param->log_mc_entry_sz, outbox,
-                        INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
-               MLX4_GET(param->log_mc_hash_sz,  outbox,
-                        INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
-               MLX4_GET(param->log_mc_table_sz, outbox,
-                        INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
+               MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_ENTRY_SZ_OFFSET);
+               param->log_mc_entry_sz = byte_field & 0x1f;
+               MLX4_GET(byte_field,  outbox, INIT_HCA_LOG_MC_HASH_SZ_OFFSET);
+               param->log_mc_hash_sz = byte_field & 0x1f;
+               MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MC_TABLE_SZ_OFFSET);
+               param->log_mc_table_sz = byte_field & 0x1f;
        }
 
        /* CX3 is capable of extending CQEs/EQEs from 32 to 64 bytes */
@@ -2167,15 +2181,18 @@ int mlx4_QUERY_HCA(struct mlx4_dev *dev,
        /* TPT attributes */
 
        MLX4_GET(param->dmpt_base,  outbox, INIT_HCA_DMPT_BASE_OFFSET);
-       MLX4_GET(param->mw_enabled, outbox, INIT_HCA_TPT_MW_OFFSET);
-       MLX4_GET(param->log_mpt_sz, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
+       MLX4_GET(byte_field, outbox, INIT_HCA_TPT_MW_OFFSET);
+       param->mw_enabled = byte_field >> 7;
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_MPT_SZ_OFFSET);
+       param->log_mpt_sz = byte_field & 0x3f;
        MLX4_GET(param->mtt_base,   outbox, INIT_HCA_MTT_BASE_OFFSET);
        MLX4_GET(param->cmpt_base,  outbox, INIT_HCA_CMPT_BASE_OFFSET);
 
        /* UAR attributes */
 
        MLX4_GET(param->uar_page_sz, outbox, INIT_HCA_UAR_PAGE_SZ_OFFSET);
-       MLX4_GET(param->log_uar_sz, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
+       MLX4_GET(byte_field, outbox, INIT_HCA_LOG_UAR_SZ_OFFSET);
+       param->log_uar_sz = byte_field & 0xf;
 
        /* phv_check enable */
        MLX4_GET(byte_field, outbox, INIT_HCA_CACHELINE_SZ_OFFSET);
index 4b43511..d89a3da 100644 (file)
@@ -57,12 +57,12 @@ static void mlx4_free_icm_pages(struct mlx4_dev *dev, struct mlx4_icm_chunk *chu
        int i;
 
        if (chunk->nsg > 0)
-               pci_unmap_sg(dev->persist->pdev, chunk->mem, chunk->npages,
-                            PCI_DMA_BIDIRECTIONAL);
+               dma_unmap_sg(&dev->persist->pdev->dev, chunk->sg, chunk->npages,
+                            DMA_BIDIRECTIONAL);
 
        for (i = 0; i < chunk->npages; ++i)
-               __free_pages(sg_page(&chunk->mem[i]),
-                            get_order(chunk->mem[i].length));
+               __free_pages(sg_page(&chunk->sg[i]),
+                            get_order(chunk->sg[i].length));
 }
 
 static void mlx4_free_icm_coherent(struct mlx4_dev *dev, struct mlx4_icm_chunk *chunk)
@@ -71,9 +71,9 @@ static void mlx4_free_icm_coherent(struct mlx4_dev *dev, struct mlx4_icm_chunk *
 
        for (i = 0; i < chunk->npages; ++i)
                dma_free_coherent(&dev->persist->pdev->dev,
-                                 chunk->mem[i].length,
-                                 lowmem_page_address(sg_page(&chunk->mem[i])),
-                                 sg_dma_address(&chunk->mem[i]));
+                                 chunk->buf[i].size,
+                                 chunk->buf[i].addr,
+                                 chunk->buf[i].dma_addr);
 }
 
 void mlx4_free_icm(struct mlx4_dev *dev, struct mlx4_icm *icm, int coherent)
@@ -111,22 +111,21 @@ static int mlx4_alloc_icm_pages(struct scatterlist *mem, int order,
        return 0;
 }
 
-static int mlx4_alloc_icm_coherent(struct device *dev, struct scatterlist *mem,
-                                   int order, gfp_t gfp_mask)
+static int mlx4_alloc_icm_coherent(struct device *dev, struct mlx4_icm_buf *buf,
+                                  int order, gfp_t gfp_mask)
 {
-       void *buf = dma_alloc_coherent(dev, PAGE_SIZE << order,
-                                      &sg_dma_address(mem), gfp_mask);
-       if (!buf)
+       buf->addr = dma_alloc_coherent(dev, PAGE_SIZE << order,
+                                      &buf->dma_addr, gfp_mask);
+       if (!buf->addr)
                return -ENOMEM;
 
-       if (offset_in_page(buf)) {
-               dma_free_coherent(dev, PAGE_SIZE << order,
-                                 buf, sg_dma_address(mem));
+       if (offset_in_page(buf->addr)) {
+               dma_free_coherent(dev, PAGE_SIZE << order, buf->addr,
+                                 buf->dma_addr);
                return -ENOMEM;
        }
 
-       sg_set_buf(mem, buf, PAGE_SIZE << order);
-       sg_dma_len(mem) = PAGE_SIZE << order;
+       buf->size = PAGE_SIZE << order;
        return 0;
 }
 
@@ -159,21 +158,21 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
 
        while (npages > 0) {
                if (!chunk) {
-                       chunk = kmalloc_node(sizeof(*chunk),
+                       chunk = kzalloc_node(sizeof(*chunk),
                                             gfp_mask & ~(__GFP_HIGHMEM |
                                                          __GFP_NOWARN),
                                             dev->numa_node);
                        if (!chunk) {
-                               chunk = kmalloc(sizeof(*chunk),
+                               chunk = kzalloc(sizeof(*chunk),
                                                gfp_mask & ~(__GFP_HIGHMEM |
                                                             __GFP_NOWARN));
                                if (!chunk)
                                        goto fail;
                        }
+                       chunk->coherent = coherent;
 
-                       sg_init_table(chunk->mem, MLX4_ICM_CHUNK_LEN);
-                       chunk->npages = 0;
-                       chunk->nsg    = 0;
+                       if (!coherent)
+                               sg_init_table(chunk->sg, MLX4_ICM_CHUNK_LEN);
                        list_add_tail(&chunk->list, &icm->chunk_list);
                }
 
@@ -186,10 +185,10 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
 
                if (coherent)
                        ret = mlx4_alloc_icm_coherent(&dev->persist->pdev->dev,
-                                                     &chunk->mem[chunk->npages],
-                                                     cur_order, mask);
+                                               &chunk->buf[chunk->npages],
+                                               cur_order, mask);
                else
-                       ret = mlx4_alloc_icm_pages(&chunk->mem[chunk->npages],
+                       ret = mlx4_alloc_icm_pages(&chunk->sg[chunk->npages],
                                                   cur_order, mask,
                                                   dev->numa_node);
 
@@ -205,9 +204,9 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
                if (coherent)
                        ++chunk->nsg;
                else if (chunk->npages == MLX4_ICM_CHUNK_LEN) {
-                       chunk->nsg = pci_map_sg(dev->persist->pdev, chunk->mem,
-                                               chunk->npages,
-                                               PCI_DMA_BIDIRECTIONAL);
+                       chunk->nsg = dma_map_sg(&dev->persist->pdev->dev,
+                                               chunk->sg, chunk->npages,
+                                               DMA_BIDIRECTIONAL);
 
                        if (chunk->nsg <= 0)
                                goto fail;
@@ -220,9 +219,8 @@ struct mlx4_icm *mlx4_alloc_icm(struct mlx4_dev *dev, int npages,
        }
 
        if (!coherent && chunk) {
-               chunk->nsg = pci_map_sg(dev->persist->pdev, chunk->mem,
-                                       chunk->npages,
-                                       PCI_DMA_BIDIRECTIONAL);
+               chunk->nsg = dma_map_sg(&dev->persist->pdev->dev, chunk->sg,
+                                       chunk->npages, DMA_BIDIRECTIONAL);
 
                if (chunk->nsg <= 0)
                        goto fail;
@@ -320,7 +318,7 @@ void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj,
        u64 idx;
        struct mlx4_icm_chunk *chunk;
        struct mlx4_icm *icm;
-       struct page *page = NULL;
+       void *addr = NULL;
 
        if (!table->lowmem)
                return NULL;
@@ -336,28 +334,49 @@ void *mlx4_table_find(struct mlx4_icm_table *table, u32 obj,
 
        list_for_each_entry(chunk, &icm->chunk_list, list) {
                for (i = 0; i < chunk->npages; ++i) {
+                       dma_addr_t dma_addr;
+                       size_t len;
+
+                       if (table->coherent) {
+                               len = chunk->buf[i].size;
+                               dma_addr = chunk->buf[i].dma_addr;
+                               addr = chunk->buf[i].addr;
+                       } else {
+                               struct page *page;
+
+                               len = sg_dma_len(&chunk->sg[i]);
+                               dma_addr = sg_dma_address(&chunk->sg[i]);
+
+                               /* XXX: we should never do this for highmem
+                                * allocation.  This function either needs
+                                * to be split, or the kernel virtual address
+                                * return needs to be made optional.
+                                */
+                               page = sg_page(&chunk->sg[i]);
+                               addr = lowmem_page_address(page);
+                       }
+
                        if (dma_handle && dma_offset >= 0) {
-                               if (sg_dma_len(&chunk->mem[i]) > dma_offset)
-                                       *dma_handle = sg_dma_address(&chunk->mem[i]) +
-                                               dma_offset;
-                               dma_offset -= sg_dma_len(&chunk->mem[i]);
+                               if (len > dma_offset)
+                                       *dma_handle = dma_addr + dma_offset;
+                               dma_offset -= len;
                        }
+
                        /*
                         * DMA mapping can merge pages but not split them,
                         * so if we found the page, dma_handle has already
                         * been assigned to.
                         */
-                       if (chunk->mem[i].length > offset) {
-                               page = sg_page(&chunk->mem[i]);
+                       if (len > offset)
                                goto out;
-                       }
-                       offset -= chunk->mem[i].length;
+                       offset -= len;
                }
        }
 
+       addr = NULL;
 out:
        mutex_unlock(&table->mutex);
-       return page ? lowmem_page_address(page) + offset : NULL;
+       return addr ? addr + offset : NULL;
 }
 
 int mlx4_table_get_range(struct mlx4_dev *dev, struct mlx4_icm_table *table,
index c9169a4..d199874 100644 (file)
@@ -47,11 +47,21 @@ enum {
        MLX4_ICM_PAGE_SIZE      = 1 << MLX4_ICM_PAGE_SHIFT,
 };
 
+struct mlx4_icm_buf {
+       void                    *addr;
+       size_t                  size;
+       dma_addr_t              dma_addr;
+};
+
 struct mlx4_icm_chunk {
        struct list_head        list;
        int                     npages;
        int                     nsg;
-       struct scatterlist      mem[MLX4_ICM_CHUNK_LEN];
+       bool                    coherent;
+       union {
+               struct scatterlist      sg[MLX4_ICM_CHUNK_LEN];
+               struct mlx4_icm_buf     buf[MLX4_ICM_CHUNK_LEN];
+       };
 };
 
 struct mlx4_icm {
@@ -114,12 +124,18 @@ static inline void mlx4_icm_next(struct mlx4_icm_iter *iter)
 
 static inline dma_addr_t mlx4_icm_addr(struct mlx4_icm_iter *iter)
 {
-       return sg_dma_address(&iter->chunk->mem[iter->page_idx]);
+       if (iter->chunk->coherent)
+               return iter->chunk->buf[iter->page_idx].dma_addr;
+       else
+               return sg_dma_address(&iter->chunk->sg[iter->page_idx]);
 }
 
 static inline unsigned long mlx4_icm_size(struct mlx4_icm_iter *iter)
 {
-       return sg_dma_len(&iter->chunk->mem[iter->page_idx]);
+       if (iter->chunk->coherent)
+               return iter->chunk->buf[iter->page_idx].size;
+       else
+               return sg_dma_len(&iter->chunk->sg[iter->page_idx]);
 }
 
 int mlx4_MAP_ICM_AUX(struct mlx4_dev *dev, struct mlx4_icm *icm);
index 456f300..421b9c3 100644 (file)
@@ -63,8 +63,8 @@ static void *mlx5_dma_zalloc_coherent_node(struct mlx5_core_dev *dev,
        mutex_lock(&priv->alloc_mutex);
        original_node = dev_to_node(&dev->pdev->dev);
        set_dev_node(&dev->pdev->dev, node);
-       cpu_handle = dma_zalloc_coherent(&dev->pdev->dev, size,
-                                        dma_handle, GFP_KERNEL);
+       cpu_handle = dma_alloc_coherent(&dev->pdev->dev, size, dma_handle,
+                                       GFP_KERNEL);
        set_dev_node(&dev->pdev->dev, original_node);
        mutex_unlock(&priv->alloc_mutex);
        return cpu_handle;
index d3125cd..e267ff9 100644 (file)
@@ -1583,6 +1583,24 @@ no_trig:
        spin_unlock_irqrestore(&dev->cmd.alloc_lock, flags);
 }
 
+void mlx5_cmd_flush(struct mlx5_core_dev *dev)
+{
+       struct mlx5_cmd *cmd = &dev->cmd;
+       int i;
+
+       for (i = 0; i < cmd->max_reg_cmds; i++)
+               while (down_trylock(&cmd->sem))
+                       mlx5_cmd_trigger_completions(dev);
+
+       while (down_trylock(&cmd->pages_sem))
+               mlx5_cmd_trigger_completions(dev);
+
+       /* Unlock cmdif */
+       up(&cmd->pages_sem);
+       for (i = 0; i < cmd->max_reg_cmds; i++)
+               up(&cmd->sem);
+}
+
 static int status_to_err(u8 status)
 {
        return status ? -1 : 0; /* TBD more meaningful codes */
@@ -1789,8 +1807,8 @@ static int alloc_cmd_page(struct mlx5_core_dev *dev, struct mlx5_cmd *cmd)
 {
        struct device *ddev = &dev->pdev->dev;
 
-       cmd->cmd_alloc_buf = dma_zalloc_coherent(ddev, MLX5_ADAPTER_PAGE_SIZE,
-                                                &cmd->alloc_dma, GFP_KERNEL);
+       cmd->cmd_alloc_buf = dma_alloc_coherent(ddev, MLX5_ADAPTER_PAGE_SIZE,
+                                               &cmd->alloc_dma, GFP_KERNEL);
        if (!cmd->cmd_alloc_buf)
                return -ENOMEM;
 
@@ -1804,9 +1822,9 @@ static int alloc_cmd_page(struct mlx5_core_dev *dev, struct mlx5_cmd *cmd)
 
        dma_free_coherent(ddev, MLX5_ADAPTER_PAGE_SIZE, cmd->cmd_alloc_buf,
                          cmd->alloc_dma);
-       cmd->cmd_alloc_buf = dma_zalloc_coherent(ddev,
-                                                2 * MLX5_ADAPTER_PAGE_SIZE - 1,
-                                                &cmd->alloc_dma, GFP_KERNEL);
+       cmd->cmd_alloc_buf = dma_alloc_coherent(ddev,
+                                               2 * MLX5_ADAPTER_PAGE_SIZE - 1,
+                                               &cmd->alloc_dma, GFP_KERNEL);
        if (!cmd->cmd_alloc_buf)
                return -ENOMEM;
 
index 8fa8fdd..448a925 100644 (file)
@@ -657,6 +657,7 @@ struct mlx5e_channel_stats {
 enum {
        MLX5E_STATE_OPENED,
        MLX5E_STATE_DESTROYING,
+       MLX5E_STATE_XDP_TX_ENABLED,
 };
 
 struct mlx5e_rqt {
index 046948e..f3c7ab6 100644 (file)
@@ -256,6 +256,7 @@ int mlx5e_tc_tun_create_header_ipv4(struct mlx5e_priv *priv,
        e->m_neigh.family = n->ops->family;
        memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
        e->out_dev = out_dev;
+       e->route_dev = route_dev;
 
        /* It's important to add the neigh to the hash table before checking
         * the neigh validity state. So if we'll get a notification, in case the
@@ -369,6 +370,7 @@ int mlx5e_tc_tun_create_header_ipv6(struct mlx5e_priv *priv,
        e->m_neigh.family = n->ops->family;
        memcpy(&e->m_neigh.dst_ip, n->primary_key, n->tbl->key_len);
        e->out_dev = out_dev;
+       e->route_dev = route_dev;
 
        /* It's importent to add the neigh to the hash table before checking
         * the neigh validity state. So if we'll get a notification, in case the
@@ -612,16 +614,18 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
                       struct mlx5_flow_spec *spec,
                       struct tc_cls_flower_offload *f,
                       void *headers_c,
-                      void *headers_v)
+                      void *headers_v, u8 *match_level)
 {
        int tunnel_type;
        int err = 0;
 
        tunnel_type = mlx5e_tc_tun_get_type(filter_dev);
        if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_VXLAN) {
+               *match_level = MLX5_MATCH_L4;
                err = mlx5e_tc_tun_parse_vxlan(priv, spec, f,
                                               headers_c, headers_v);
        } else if (tunnel_type == MLX5E_TC_TUNNEL_TYPE_GRETAP) {
+               *match_level = MLX5_MATCH_L3;
                err = mlx5e_tc_tun_parse_gretap(priv, spec, f,
                                                headers_c, headers_v);
        } else {
index 706ce7b..b63f15d 100644 (file)
@@ -39,6 +39,6 @@ int mlx5e_tc_tun_parse(struct net_device *filter_dev,
                       struct mlx5_flow_spec *spec,
                       struct tc_cls_flower_offload *f,
                       void *headers_c,
-                      void *headers_v);
+                      void *headers_v, u8 *match_level);
 
 #endif //__MLX5_EN_TC_TUNNEL_H__
index 3740177..03b2a9f 100644 (file)
@@ -365,7 +365,8 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
        int sq_num;
        int i;
 
-       if (unlikely(!test_bit(MLX5E_STATE_OPENED, &priv->state)))
+       /* this flag is sufficient, no need to test internal sq state */
+       if (unlikely(!mlx5e_xdp_tx_is_enabled(priv)))
                return -ENETDOWN;
 
        if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK))
@@ -378,9 +379,6 @@ int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
 
        sq = &priv->channels.c[sq_num]->xdpsq;
 
-       if (unlikely(!test_bit(MLX5E_SQ_STATE_ENABLED, &sq->state)))
-               return -ENETDOWN;
-
        for (i = 0; i < n; i++) {
                struct xdp_frame *xdpf = frames[i];
                struct mlx5e_xdp_info xdpi;
index 3a67cb3..ee27a7c 100644 (file)
@@ -50,6 +50,23 @@ void mlx5e_xdp_rx_poll_complete(struct mlx5e_rq *rq);
 int mlx5e_xdp_xmit(struct net_device *dev, int n, struct xdp_frame **frames,
                   u32 flags);
 
+static inline void mlx5e_xdp_tx_enable(struct mlx5e_priv *priv)
+{
+       set_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
+}
+
+static inline void mlx5e_xdp_tx_disable(struct mlx5e_priv *priv)
+{
+       clear_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
+       /* let other device's napi(s) see our new state */
+       synchronize_rcu();
+}
+
+static inline bool mlx5e_xdp_tx_is_enabled(struct mlx5e_priv *priv)
+{
+       return test_bit(MLX5E_STATE_XDP_TX_ENABLED, &priv->state);
+}
+
 static inline void mlx5e_xmit_xdp_doorbell(struct mlx5e_xdpsq *sq)
 {
        if (sq->doorbell_cseg) {
index c9df081..47233b9 100644 (file)
@@ -354,9 +354,6 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
 
        new_channels.params = priv->channels.params;
        new_channels.params.num_channels = count;
-       if (!netif_is_rxfh_configured(priv->netdev))
-               mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
-                                             MLX5E_INDIR_RQT_SIZE, count);
 
        if (!test_bit(MLX5E_STATE_OPENED, &priv->state)) {
                priv->channels.params = new_channels.params;
@@ -372,6 +369,10 @@ int mlx5e_ethtool_set_channels(struct mlx5e_priv *priv,
        if (arfs_enabled)
                mlx5e_arfs_disable(priv);
 
+       if (!netif_is_rxfh_configured(priv->netdev))
+               mlx5e_build_default_indir_rqt(priv->rss_params.indirection_rqt,
+                                             MLX5E_INDIR_RQT_SIZE, count);
+
        /* Switch to new channels, set new parameters and close old ones */
        mlx5e_switch_priv_channels(priv, &new_channels, NULL);
 
@@ -844,9 +845,12 @@ int mlx5e_ethtool_get_link_ksettings(struct mlx5e_priv *priv,
        ethtool_link_ksettings_add_link_mode(link_ksettings, supported,
                                             Autoneg);
 
-       if (get_fec_supported_advertised(mdev, link_ksettings))
+       err = get_fec_supported_advertised(mdev, link_ksettings);
+       if (err) {
                netdev_dbg(priv->netdev, "%s: FEC caps query failed: %d\n",
                           __func__, err);
+               err = 0; /* don't fail caps query because of FEC error */
+       }
 
        if (!an_disable_admin)
                ethtool_link_ksettings_add_link_mode(link_ksettings,
index 8cfd2ec..93e50cc 100644 (file)
@@ -950,7 +950,7 @@ static int mlx5e_open_rq(struct mlx5e_channel *c,
        if (params->rx_dim_enabled)
                __set_bit(MLX5E_RQ_STATE_AM, &c->rq.state);
 
-       if (params->pflags & MLX5E_PFLAG_RX_NO_CSUM_COMPLETE)
+       if (MLX5E_GET_PFLAG(params, MLX5E_PFLAG_RX_NO_CSUM_COMPLETE))
                __set_bit(MLX5E_RQ_STATE_NO_CSUM_COMPLETE, &c->rq.state);
 
        return 0;
@@ -2938,6 +2938,7 @@ void mlx5e_activate_priv_channels(struct mlx5e_priv *priv)
 
        mlx5e_build_tx2sq_maps(priv);
        mlx5e_activate_channels(&priv->channels);
+       mlx5e_xdp_tx_enable(priv);
        netif_tx_start_all_queues(priv->netdev);
 
        if (mlx5e_is_vport_rep(priv))
@@ -2959,6 +2960,7 @@ void mlx5e_deactivate_priv_channels(struct mlx5e_priv *priv)
         */
        netif_tx_stop_all_queues(priv->netdev);
        netif_tx_disable(priv->netdev);
+       mlx5e_xdp_tx_disable(priv);
        mlx5e_deactivate_channels(&priv->channels);
 }
 
index 96cc0c6..ef9e472 100644 (file)
@@ -58,7 +58,8 @@ struct mlx5e_rep_indr_block_priv {
        struct list_head list;
 };
 
-static void mlx5e_rep_indr_unregister_block(struct net_device *netdev);
+static void mlx5e_rep_indr_unregister_block(struct mlx5e_rep_priv *rpriv,
+                                           struct net_device *netdev);
 
 static void mlx5e_rep_get_drvinfo(struct net_device *dev,
                                  struct ethtool_drvinfo *drvinfo)
@@ -179,6 +180,7 @@ static void mlx5e_rep_update_sw_counters(struct mlx5e_priv *priv)
 
                        s->tx_packets           += sq_stats->packets;
                        s->tx_bytes             += sq_stats->bytes;
+                       s->tx_queue_dropped     += sq_stats->dropped;
                }
        }
 }
@@ -594,6 +596,10 @@ static void mlx5e_rep_update_flows(struct mlx5e_priv *priv,
        if (neigh_connected && !(e->flags & MLX5_ENCAP_ENTRY_VALID)) {
                ether_addr_copy(e->h_dest, ha);
                ether_addr_copy(eth->h_dest, ha);
+               /* Update the encap source mac, in case that we delete
+                * the flows when encap source mac changed.
+                */
+               ether_addr_copy(eth->h_source, e->route_dev->dev_addr);
 
                mlx5e_tc_encap_flows_add(priv, e);
        }
@@ -663,7 +669,7 @@ static void mlx5e_rep_indr_clean_block_privs(struct mlx5e_rep_priv *rpriv)
        struct list_head *head = &rpriv->uplink_priv.tc_indr_block_priv_list;
 
        list_for_each_entry_safe(cb_priv, temp, head, list) {
-               mlx5e_rep_indr_unregister_block(cb_priv->netdev);
+               mlx5e_rep_indr_unregister_block(rpriv, cb_priv->netdev);
                kfree(cb_priv);
        }
 }
@@ -735,7 +741,7 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
 
                err = tcf_block_cb_register(f->block,
                                            mlx5e_rep_indr_setup_block_cb,
-                                           netdev, indr_priv, f->extack);
+                                           indr_priv, indr_priv, f->extack);
                if (err) {
                        list_del(&indr_priv->list);
                        kfree(indr_priv);
@@ -743,14 +749,15 @@ mlx5e_rep_indr_setup_tc_block(struct net_device *netdev,
 
                return err;
        case TC_BLOCK_UNBIND:
+               indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev);
+               if (!indr_priv)
+                       return -ENOENT;
+
                tcf_block_cb_unregister(f->block,
                                        mlx5e_rep_indr_setup_block_cb,
-                                       netdev);
-               indr_priv = mlx5e_rep_indr_block_priv_lookup(rpriv, netdev);
-               if (indr_priv) {
-                       list_del(&indr_priv->list);
-                       kfree(indr_priv);
-               }
+                                       indr_priv);
+               list_del(&indr_priv->list);
+               kfree(indr_priv);
 
                return 0;
        default:
@@ -779,7 +786,7 @@ static int mlx5e_rep_indr_register_block(struct mlx5e_rep_priv *rpriv,
 
        err = __tc_indr_block_cb_register(netdev, rpriv,
                                          mlx5e_rep_indr_setup_tc_cb,
-                                         netdev);
+                                         rpriv);
        if (err) {
                struct mlx5e_priv *priv = netdev_priv(rpriv->netdev);
 
@@ -789,10 +796,11 @@ static int mlx5e_rep_indr_register_block(struct mlx5e_rep_priv *rpriv,
        return err;
 }
 
-static void mlx5e_rep_indr_unregister_block(struct net_device *netdev)
+static void mlx5e_rep_indr_unregister_block(struct mlx5e_rep_priv *rpriv,
+                                           struct net_device *netdev)
 {
        __tc_indr_block_cb_unregister(netdev, mlx5e_rep_indr_setup_tc_cb,
-                                     netdev);
+                                     rpriv);
 }
 
 static int mlx5e_nic_rep_netdevice_event(struct notifier_block *nb,
@@ -811,7 +819,7 @@ static int mlx5e_nic_rep_netdevice_event(struct notifier_block *nb,
                mlx5e_rep_indr_register_block(rpriv, netdev);
                break;
        case NETDEV_UNREGISTER:
-               mlx5e_rep_indr_unregister_block(netdev);
+               mlx5e_rep_indr_unregister_block(rpriv, netdev);
                break;
        }
        return NOTIFY_OK;
@@ -1122,9 +1130,17 @@ static int mlx5e_rep_get_phys_port_name(struct net_device *dev,
        struct mlx5e_priv *priv = netdev_priv(dev);
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
        struct mlx5_eswitch_rep *rep = rpriv->rep;
-       int ret;
+       int ret, pf_num;
+
+       ret = mlx5_lag_get_pf_num(priv->mdev, &pf_num);
+       if (ret)
+               return ret;
+
+       if (rep->vport == FDB_UPLINK_VPORT)
+               ret = snprintf(buf, len, "p%d", pf_num);
+       else
+               ret = snprintf(buf, len, "pf%dvf%d", pf_num, rep->vport - 1);
 
-       ret = snprintf(buf, len, "%d", rep->vport - 1);
        if (ret >= len)
                return -EOPNOTSUPP;
 
@@ -1281,6 +1297,18 @@ static int mlx5e_uplink_rep_set_mac(struct net_device *netdev, void *addr)
        return 0;
 }
 
+static int mlx5e_uplink_rep_set_vf_vlan(struct net_device *dev, int vf, u16 vlan, u8 qos,
+                                       __be16 vlan_proto)
+{
+       netdev_warn_once(dev, "legacy vf vlan setting isn't supported in switchdev mode\n");
+
+       if (vlan != 0)
+               return -EOPNOTSUPP;
+
+       /* allow setting 0-vid for compatibility with libvirt */
+       return 0;
+}
+
 static const struct switchdev_ops mlx5e_rep_switchdev_ops = {
        .switchdev_port_attr_get        = mlx5e_attr_get,
 };
@@ -1315,6 +1343,7 @@ static const struct net_device_ops mlx5e_netdev_ops_uplink_rep = {
        .ndo_set_vf_rate         = mlx5e_set_vf_rate,
        .ndo_get_vf_config       = mlx5e_get_vf_config,
        .ndo_get_vf_stats        = mlx5e_get_vf_stats,
+       .ndo_set_vf_vlan         = mlx5e_uplink_rep_set_vf_vlan,
 };
 
 bool mlx5e_eswitch_rep(struct net_device *netdev)
index edd7228..36eafc8 100644 (file)
@@ -148,6 +148,7 @@ struct mlx5e_encap_entry {
        unsigned char h_dest[ETH_ALEN]; /* destination eth addr */
 
        struct net_device *out_dev;
+       struct net_device *route_dev;
        int tunnel_type;
        int tunnel_hlen;
        int reformat_type;
index 1d0bb5f..f86e480 100644 (file)
@@ -732,6 +732,8 @@ static u8 get_ip_proto(struct sk_buff *skb, int network_depth, __be16 proto)
                                            ((struct ipv6hdr *)ip_p)->nexthdr;
 }
 
+#define short_frame(size) ((size) <= ETH_ZLEN + ETH_FCS_LEN)
+
 static inline void mlx5e_handle_csum(struct net_device *netdev,
                                     struct mlx5_cqe64 *cqe,
                                     struct mlx5e_rq *rq,
@@ -754,6 +756,17 @@ static inline void mlx5e_handle_csum(struct net_device *netdev,
        if (unlikely(test_bit(MLX5E_RQ_STATE_NO_CSUM_COMPLETE, &rq->state)))
                goto csum_unnecessary;
 
+       /* CQE csum doesn't cover padding octets in short ethernet
+        * frames. And the pad field is appended prior to calculating
+        * and appending the FCS field.
+        *
+        * Detecting these padded frames requires to verify and parse
+        * IP headers, so we simply force all those small frames to be
+        * CHECKSUM_UNNECESSARY even if they are not padded.
+        */
+       if (short_frame(skb->len))
+               goto csum_unnecessary;
+
        if (likely(is_last_ethertype_ip(skb, &network_depth, &proto))) {
                if (unlikely(get_ip_proto(skb, network_depth, proto) == IPPROTO_SCTP))
                        goto csum_unnecessary;
index cae6c6d..b5c1b03 100644 (file)
@@ -128,6 +128,7 @@ struct mlx5e_tc_flow_parse_attr {
        struct net_device *filter_dev;
        struct mlx5_flow_spec spec;
        int num_mod_hdr_actions;
+       int max_mod_hdr_actions;
        void *mod_hdr_actions;
        int mirred_ifindex[MLX5_MAX_FLOW_FWD_VPORTS];
 };
@@ -1302,7 +1303,7 @@ static void mlx5e_tc_del_flow(struct mlx5e_priv *priv,
 static int parse_tunnel_attr(struct mlx5e_priv *priv,
                             struct mlx5_flow_spec *spec,
                             struct tc_cls_flower_offload *f,
-                            struct net_device *filter_dev)
+                            struct net_device *filter_dev, u8 *match_level)
 {
        struct netlink_ext_ack *extack = f->common.extack;
        void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
@@ -1317,7 +1318,7 @@ static int parse_tunnel_attr(struct mlx5e_priv *priv,
        int err = 0;
 
        err = mlx5e_tc_tun_parse(filter_dev, priv, spec, f,
-                                headers_c, headers_v);
+                                headers_c, headers_v, match_level);
        if (err) {
                NL_SET_ERR_MSG_MOD(extack,
                                   "failed to parse tunnel attributes");
@@ -1426,7 +1427,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                              struct mlx5_flow_spec *spec,
                              struct tc_cls_flower_offload *f,
                              struct net_device *filter_dev,
-                             u8 *match_level)
+                             u8 *match_level, u8 *tunnel_match_level)
 {
        struct netlink_ext_ack *extack = f->common.extack;
        void *headers_c = MLX5_ADDR_OF(fte_match_param, spec->match_criteria,
@@ -1477,7 +1478,7 @@ static int __parse_cls_flower(struct mlx5e_priv *priv,
                switch (key->addr_type) {
                case FLOW_DISSECTOR_KEY_IPV4_ADDRS:
                case FLOW_DISSECTOR_KEY_IPV6_ADDRS:
-                       if (parse_tunnel_attr(priv, spec, f, filter_dev))
+                       if (parse_tunnel_attr(priv, spec, f, filter_dev, tunnel_match_level))
                                return -EOPNOTSUPP;
                        break;
                default:
@@ -1826,11 +1827,11 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
        struct mlx5_core_dev *dev = priv->mdev;
        struct mlx5_eswitch *esw = dev->priv.eswitch;
        struct mlx5e_rep_priv *rpriv = priv->ppriv;
+       u8 match_level, tunnel_match_level = MLX5_MATCH_NONE;
        struct mlx5_eswitch_rep *rep;
-       u8 match_level;
        int err;
 
-       err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level);
+       err = __parse_cls_flower(priv, spec, f, filter_dev, &match_level, &tunnel_match_level);
 
        if (!err && (flow->flags & MLX5E_TC_FLOW_ESWITCH)) {
                rep = rpriv->rep;
@@ -1846,10 +1847,12 @@ static int parse_cls_flower(struct mlx5e_priv *priv,
                }
        }
 
-       if (flow->flags & MLX5E_TC_FLOW_ESWITCH)
+       if (flow->flags & MLX5E_TC_FLOW_ESWITCH) {
                flow->esw_attr->match_level = match_level;
-       else
+               flow->esw_attr->tunnel_match_level = tunnel_match_level;
+       } else {
                flow->nic_attr->match_level = match_level;
+       }
 
        return err;
 }
@@ -1934,9 +1937,9 @@ static struct mlx5_fields fields[] = {
        OFFLOAD(UDP_DPORT, 2, udp.dest,   0),
 };
 
-/* On input attr->num_mod_hdr_actions tells how many HW actions can be parsed at
- * max from the SW pedit action. On success, it says how many HW actions were
- * actually parsed.
+/* On input attr->max_mod_hdr_actions tells how many HW actions can be parsed at
+ * max from the SW pedit action. On success, attr->num_mod_hdr_actions
+ * says how many HW actions were actually parsed.
  */
 static int offload_pedit_fields(struct pedit_headers *masks,
                                struct pedit_headers *vals,
@@ -1960,9 +1963,11 @@ static int offload_pedit_fields(struct pedit_headers *masks,
        add_vals = &vals[TCA_PEDIT_KEY_EX_CMD_ADD];
 
        action_size = MLX5_UN_SZ_BYTES(set_action_in_add_action_in_auto);
-       action = parse_attr->mod_hdr_actions;
-       max_actions = parse_attr->num_mod_hdr_actions;
-       nactions = 0;
+       action = parse_attr->mod_hdr_actions +
+                parse_attr->num_mod_hdr_actions * action_size;
+
+       max_actions = parse_attr->max_mod_hdr_actions;
+       nactions = parse_attr->num_mod_hdr_actions;
 
        for (i = 0; i < ARRAY_SIZE(fields); i++) {
                f = &fields[i];
@@ -2073,7 +2078,7 @@ static int alloc_mod_hdr_actions(struct mlx5e_priv *priv,
        if (!parse_attr->mod_hdr_actions)
                return -ENOMEM;
 
-       parse_attr->num_mod_hdr_actions = max_actions;
+       parse_attr->max_mod_hdr_actions = max_actions;
        return 0;
 }
 
@@ -2119,9 +2124,11 @@ static int parse_tc_pedit_action(struct mlx5e_priv *priv,
                        goto out_err;
        }
 
-       err = alloc_mod_hdr_actions(priv, a, namespace, parse_attr);
-       if (err)
-               goto out_err;
+       if (!parse_attr->mod_hdr_actions) {
+               err = alloc_mod_hdr_actions(priv, a, namespace, parse_attr);
+               if (err)
+                       goto out_err;
+       }
 
        err = offload_pedit_fields(masks, vals, parse_attr, extack);
        if (err < 0)
@@ -2179,6 +2186,7 @@ static bool csum_offload_supported(struct mlx5e_priv *priv,
 
 static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
                                          struct tcf_exts *exts,
+                                         u32 actions,
                                          struct netlink_ext_ack *extack)
 {
        const struct tc_action *a;
@@ -2188,7 +2196,11 @@ static bool modify_header_match_supported(struct mlx5_flow_spec *spec,
        u16 ethertype;
        int nkeys, i;
 
-       headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers);
+       if (actions & MLX5_FLOW_CONTEXT_ACTION_DECAP)
+               headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, inner_headers);
+       else
+               headers_v = MLX5_ADDR_OF(fte_match_param, spec->match_value, outer_headers);
+
        ethertype = MLX5_GET(fte_match_set_lyr_2_4, headers_v, ethertype);
 
        /* for non-IP we only re-write MACs, so we're okay */
@@ -2245,7 +2257,7 @@ static bool actions_match_supported(struct mlx5e_priv *priv,
 
        if (actions & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
                return modify_header_match_supported(&parse_attr->spec, exts,
-                                                    extack);
+                                                    actions, extack);
 
        return true;
 }
index 598ad7e..0e55cd1 100644 (file)
@@ -387,8 +387,14 @@ netdev_tx_t mlx5e_sq_xmit(struct mlx5e_txqsq *sq, struct sk_buff *skb,
        num_wqebbs = DIV_ROUND_UP(ds_cnt, MLX5_SEND_WQEBB_NUM_DS);
        contig_wqebbs_room = mlx5_wq_cyc_get_contig_wqebbs(wq, pi);
        if (unlikely(contig_wqebbs_room < num_wqebbs)) {
+#ifdef CONFIG_MLX5_EN_IPSEC
+               struct mlx5_wqe_eth_seg cur_eth = wqe->eth;
+#endif
                mlx5e_fill_sq_frag_edge(sq, wq, pi, contig_wqebbs_room);
                mlx5e_sq_fetch_wqe(sq, &wqe, &pi);
+#ifdef CONFIG_MLX5_EN_IPSEC
+               wqe->eth = cur_eth;
+#endif
        }
 
        /* fill wqe */
index a44ea7b..5b492b6 100644 (file)
@@ -1134,13 +1134,6 @@ static int esw_vport_ingress_config(struct mlx5_eswitch *esw,
        int err = 0;
        u8 *smac_v;
 
-       if (vport->info.spoofchk && !is_valid_ether_addr(vport->info.mac)) {
-               mlx5_core_warn(esw->dev,
-                              "vport[%d] configure ingress rules failed, illegal mac with spoofchk\n",
-                              vport->vport);
-               return -EPERM;
-       }
-
        esw_vport_cleanup_ingress_rules(esw, vport);
 
        if (!vport->info.vlan && !vport->info.qos && !vport->info.spoofchk) {
@@ -1728,7 +1721,7 @@ int mlx5_eswitch_init(struct mlx5_core_dev *dev)
        int vport_num;
        int err;
 
-       if (!MLX5_ESWITCH_MANAGER(dev))
+       if (!MLX5_VPORT_MANAGER(dev))
                return 0;
 
        esw_info(dev,
@@ -1797,7 +1790,7 @@ abort:
 
 void mlx5_eswitch_cleanup(struct mlx5_eswitch *esw)
 {
-       if (!esw || !MLX5_ESWITCH_MANAGER(esw->dev))
+       if (!esw || !MLX5_VPORT_MANAGER(esw->dev))
                return;
 
        esw_info(esw->dev, "cleanup\n");
@@ -1827,13 +1820,10 @@ int mlx5_eswitch_set_vport_mac(struct mlx5_eswitch *esw,
        mutex_lock(&esw->state_lock);
        evport = &esw->vports[vport];
 
-       if (evport->info.spoofchk && !is_valid_ether_addr(mac)) {
+       if (evport->info.spoofchk && !is_valid_ether_addr(mac))
                mlx5_core_warn(esw->dev,
-                              "MAC invalidation is not allowed when spoofchk is on, vport(%d)\n",
+                              "Set invalid MAC while spoofchk is on, vport(%d)\n",
                               vport);
-               err = -EPERM;
-               goto unlock;
-       }
 
        err = mlx5_modify_nic_vport_mac_address(esw->dev, vport, mac);
        if (err) {
@@ -1979,6 +1969,10 @@ int mlx5_eswitch_set_vport_spoofchk(struct mlx5_eswitch *esw,
        evport = &esw->vports[vport];
        pschk = evport->info.spoofchk;
        evport->info.spoofchk = spoofchk;
+       if (pschk && !is_valid_ether_addr(evport->info.mac))
+               mlx5_core_warn(esw->dev,
+                              "Spoofchk in set while MAC is invalid, vport(%d)\n",
+                              evport->vport);
        if (evport->enabled && esw->mode == SRIOV_LEGACY)
                err = esw_vport_ingress_config(esw, evport);
        if (err)
index 9c89eea..748ff17 100644 (file)
@@ -312,6 +312,7 @@ struct mlx5_esw_flow_attr {
        } dests[MLX5_MAX_FLOW_FWD_VPORTS];
        u32     mod_hdr_id;
        u8      match_level;
+       u8      tunnel_match_level;
        struct mlx5_fc *counter;
        u32     chain;
        u16     prio;
index 53065b6..d4e6fe5 100644 (file)
@@ -160,14 +160,15 @@ mlx5_eswitch_add_offloaded_rule(struct mlx5_eswitch *esw,
                MLX5_SET_TO_ONES(fte_match_set_misc, misc,
                                 source_eswitch_owner_vhca_id);
 
-       if (attr->match_level == MLX5_MATCH_NONE)
-               spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
-       else
-               spec->match_criteria_enable = MLX5_MATCH_OUTER_HEADERS |
-                                             MLX5_MATCH_MISC_PARAMETERS;
-
-       if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP)
-               spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
+       spec->match_criteria_enable = MLX5_MATCH_MISC_PARAMETERS;
+       if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_DECAP) {
+               if (attr->tunnel_match_level != MLX5_MATCH_NONE)
+                       spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
+               if (attr->match_level != MLX5_MATCH_NONE)
+                       spec->match_criteria_enable |= MLX5_MATCH_INNER_HEADERS;
+       } else if (attr->match_level != MLX5_MATCH_NONE) {
+               spec->match_criteria_enable |= MLX5_MATCH_OUTER_HEADERS;
+       }
 
        if (flow_act.action & MLX5_FLOW_CONTEXT_ACTION_MOD_HDR)
                flow_act.modify_id = attr->mod_hdr_id;
index fbc42b7..5030354 100644 (file)
@@ -211,11 +211,10 @@ static int port_module(struct notifier_block *nb, unsigned long type, void *data
        enum port_module_event_status_type module_status;
        enum port_module_event_error_type error_type;
        struct mlx5_eqe_port_module *module_event_eqe;
-       const char *status_str, *error_str;
+       const char *status_str;
        u8 module_num;
 
        module_event_eqe = &eqe->data.port_module;
-       module_num = module_event_eqe->module;
        module_status = module_event_eqe->module_status &
                        PORT_MODULE_EVENT_MODULE_STATUS_MASK;
        error_type = module_event_eqe->error_type &
@@ -223,25 +222,27 @@ static int port_module(struct notifier_block *nb, unsigned long type, void *data
 
        if (module_status < MLX5_MODULE_STATUS_NUM)
                events->pme_stats.status_counters[module_status]++;
-       status_str = mlx5_pme_status_to_string(module_status);
 
-       if (module_status == MLX5_MODULE_STATUS_ERROR) {
+       if (module_status == MLX5_MODULE_STATUS_ERROR)
                if (error_type < MLX5_MODULE_EVENT_ERROR_NUM)
                        events->pme_stats.error_counters[error_type]++;
-               error_str = mlx5_pme_error_to_string(error_type);
-       }
 
        if (!printk_ratelimit())
                return NOTIFY_OK;
 
-       if (module_status == MLX5_MODULE_STATUS_ERROR)
+       module_num = module_event_eqe->module;
+       status_str = mlx5_pme_status_to_string(module_status);
+       if (module_status == MLX5_MODULE_STATUS_ERROR) {
+               const char *error_str = mlx5_pme_error_to_string(error_type);
+
                mlx5_core_err(events->dev,
                              "Port module event[error]: module %u, %s, %s\n",
                              module_num, status_str, error_str);
-       else
+       } else {
                mlx5_core_info(events->dev,
                               "Port module event: module %u, %s\n",
                               module_num, status_str);
+       }
 
        return NOTIFY_OK;
 }
index 196c073..cb9fa34 100644 (file)
@@ -103,7 +103,7 @@ void mlx5_enter_error_state(struct mlx5_core_dev *dev, bool force)
        mlx5_core_err(dev, "start\n");
        if (pci_channel_offline(dev->pdev) || in_fatal(dev) || force) {
                dev->state = MLX5_DEVICE_STATE_INTERNAL_ERROR;
-               mlx5_cmd_trigger_completions(dev);
+               mlx5_cmd_flush(dev);
        }
 
        mlx5_notifier_call_chain(dev->priv.events, MLX5_DEV_EVENT_SYS_ERROR, (void *)1);
index 3a6baed..2d22338 100644 (file)
@@ -616,6 +616,27 @@ void mlx5_lag_add(struct mlx5_core_dev *dev, struct net_device *netdev)
        }
 }
 
+int mlx5_lag_get_pf_num(struct mlx5_core_dev *dev, int *pf_num)
+{
+       struct mlx5_lag *ldev;
+       int n;
+
+       ldev = mlx5_lag_dev_get(dev);
+       if (!ldev) {
+               mlx5_core_warn(dev, "no lag device, can't get pf num\n");
+               return -EINVAL;
+       }
+
+       for (n = 0; n < MLX5_MAX_PORTS; n++)
+               if (ldev->pf[n].dev == dev) {
+                       *pf_num = n;
+                       return 0;
+               }
+
+       mlx5_core_warn(dev, "wasn't able to locate pf in the lag device\n");
+       return -EINVAL;
+}
+
 /* Must be called with intf_mutex held */
 void mlx5_lag_remove(struct mlx5_core_dev *dev)
 {
index c68dcea..4fdac02 100644 (file)
@@ -126,6 +126,7 @@ u64 mlx5_read_internal_timer(struct mlx5_core_dev *dev,
                             struct ptp_system_timestamp *sts);
 
 void mlx5_cmd_trigger_completions(struct mlx5_core_dev *dev);
+void mlx5_cmd_flush(struct mlx5_core_dev *dev);
 int mlx5_cq_debugfs_init(struct mlx5_core_dev *dev);
 void mlx5_cq_debugfs_cleanup(struct mlx5_core_dev *dev);
 
@@ -187,6 +188,8 @@ static inline int mlx5_lag_is_lacp_owner(struct mlx5_core_dev *dev)
                    MLX5_CAP_GEN(dev, lag_master);
 }
 
+int mlx5_lag_get_pf_num(struct mlx5_core_dev *dev, int *pf_num);
+
 void mlx5_reload_interface(struct mlx5_core_dev *mdev, int protocol);
 void mlx5_lag_update(struct mlx5_core_dev *dev);
 
index 388f205..370ca94 100644 (file)
@@ -44,14 +44,15 @@ static struct mlx5_core_rsc_common *
 mlx5_get_rsc(struct mlx5_qp_table *table, u32 rsn)
 {
        struct mlx5_core_rsc_common *common;
+       unsigned long flags;
 
-       spin_lock(&table->lock);
+       spin_lock_irqsave(&table->lock, flags);
 
        common = radix_tree_lookup(&table->tree, rsn);
        if (common)
                atomic_inc(&common->refcount);
 
-       spin_unlock(&table->lock);
+       spin_unlock_irqrestore(&table->lock, flags);
 
        return common;
 }
index 080ddd1..b9a25ae 100644 (file)
@@ -78,6 +78,7 @@ config MLXSW_SPECTRUM
        depends on IPV6 || IPV6=n
        depends on NET_IPGRE || NET_IPGRE=n
        depends on IPV6_GRE || IPV6_GRE=n
+       depends on VXLAN || VXLAN=n
        select GENERIC_ALLOCATOR
        select PARMAN
        select OBJAGG
index 66b8098..a2321fe 100644 (file)
@@ -604,29 +604,31 @@ static void mlxsw_pci_cq_tasklet(unsigned long data)
                u16 wqe_counter = mlxsw_pci_cqe_wqe_counter_get(cqe);
                u8 sendq = mlxsw_pci_cqe_sr_get(q->u.cq.v, cqe);
                u8 dqn = mlxsw_pci_cqe_dqn_get(q->u.cq.v, cqe);
+               char ncqe[MLXSW_PCI_CQE_SIZE_MAX];
+
+               memcpy(ncqe, cqe, q->elem_size);
+               mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
 
                if (sendq) {
                        struct mlxsw_pci_queue *sdq;
 
                        sdq = mlxsw_pci_sdq_get(mlxsw_pci, dqn);
                        mlxsw_pci_cqe_sdq_handle(mlxsw_pci, sdq,
-                                                wqe_counter, cqe);
+                                                wqe_counter, ncqe);
                        q->u.cq.comp_sdq_count++;
                } else {
                        struct mlxsw_pci_queue *rdq;
 
                        rdq = mlxsw_pci_rdq_get(mlxsw_pci, dqn);
                        mlxsw_pci_cqe_rdq_handle(mlxsw_pci, rdq,
-                                                wqe_counter, q->u.cq.v, cqe);
+                                                wqe_counter, q->u.cq.v, ncqe);
                        q->u.cq.comp_rdq_count++;
                }
                if (++items == credits)
                        break;
        }
-       if (items) {
-               mlxsw_pci_queue_doorbell_consumer_ring(mlxsw_pci, q);
+       if (items)
                mlxsw_pci_queue_doorbell_arm_consumer_ring(mlxsw_pci, q);
-       }
 }
 
 static u16 mlxsw_pci_cq_elem_count(const struct mlxsw_pci_queue *q)
@@ -1365,10 +1367,10 @@ static int mlxsw_pci_sw_reset(struct mlxsw_pci *mlxsw_pci,
                u32 val = mlxsw_pci_read32(mlxsw_pci, FW_READY);
 
                if ((val & MLXSW_PCI_FW_READY_MASK) == MLXSW_PCI_FW_READY_MAGIC)
-                       break;
+                       return 0;
                cond_resched();
        } while (time_before(jiffies, end));
-       return 0;
+       return -EBUSY;
 }
 
 static int mlxsw_pci_alloc_irq_vectors(struct mlxsw_pci *mlxsw_pci)
index bb99f6d..ffee38e 100644 (file)
@@ -27,7 +27,7 @@
 
 #define MLXSW_PCI_SW_RESET                     0xF0010
 #define MLXSW_PCI_SW_RESET_RST_BIT             BIT(0)
-#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS       5000
+#define MLXSW_PCI_SW_RESET_TIMEOUT_MSECS       13000
 #define MLXSW_PCI_SW_RESET_WAIT_MSECS          100
 #define MLXSW_PCI_FW_READY                     0xA1844
 #define MLXSW_PCI_FW_READY_MASK                        0xFFFF
@@ -53,6 +53,7 @@
 #define MLXSW_PCI_WQE_SIZE     32 /* 32 bytes per element */
 #define MLXSW_PCI_CQE01_SIZE   16 /* 16 bytes per element */
 #define MLXSW_PCI_CQE2_SIZE    32 /* 32 bytes per element */
+#define MLXSW_PCI_CQE_SIZE_MAX MLXSW_PCI_CQE2_SIZE
 #define MLXSW_PCI_EQE_SIZE     16 /* 16 bytes per element */
 #define MLXSW_PCI_WQE_COUNT    (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_WQE_SIZE)
 #define MLXSW_PCI_CQE01_COUNT  (MLXSW_PCI_AQ_SIZE / MLXSW_PCI_CQE01_SIZE)
index eed1045..b65e274 100644 (file)
@@ -862,8 +862,9 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
        for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
                bool configure = false;
                bool pfc = false;
+               u16 thres_cells;
+               u16 delay_cells;
                bool lossy;
-               u16 thres;
 
                for (j = 0; j < IEEE_8021QAZ_MAX_TCS; j++) {
                        if (prio_tc[j] == i) {
@@ -877,10 +878,11 @@ int __mlxsw_sp_port_headroom_set(struct mlxsw_sp_port *mlxsw_sp_port, int mtu,
                        continue;
 
                lossy = !(pfc || pause_en);
-               thres = mlxsw_sp_pg_buf_threshold_get(mlxsw_sp, mtu);
-               delay = mlxsw_sp_pg_buf_delay_get(mlxsw_sp, mtu, delay, pfc,
-                                                 pause_en);
-               mlxsw_sp_pg_buf_pack(pbmc_pl, i, thres + delay, thres, lossy);
+               thres_cells = mlxsw_sp_pg_buf_threshold_get(mlxsw_sp, mtu);
+               delay_cells = mlxsw_sp_pg_buf_delay_get(mlxsw_sp, mtu, delay,
+                                                       pfc, pause_en);
+               mlxsw_sp_pg_buf_pack(pbmc_pl, i, thres_cells + delay_cells,
+                                    thres_cells, lossy);
        }
 
        return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(pbmc), pbmc_pl);
@@ -5005,12 +5007,15 @@ static int mlxsw_sp_netdevice_port_upper_event(struct net_device *lower_dev,
                                                           lower_dev,
                                                           upper_dev);
                } else if (netif_is_lag_master(upper_dev)) {
-                       if (info->linking)
+                       if (info->linking) {
                                err = mlxsw_sp_port_lag_join(mlxsw_sp_port,
                                                             upper_dev);
-                       else
+                       } else {
+                               mlxsw_sp_port_lag_tx_en_set(mlxsw_sp_port,
+                                                           false);
                                mlxsw_sp_port_lag_leave(mlxsw_sp_port,
                                                        upper_dev);
+                       }
                } else if (netif_is_ovs_master(upper_dev)) {
                        if (info->linking)
                                err = mlxsw_sp_port_ovs_join(mlxsw_sp_port);
index b0f2d8e..ac22283 100644 (file)
@@ -72,7 +72,15 @@ mlxsw_sp_acl_ctcam_region_entry_insert(struct mlxsw_sp *mlxsw_sp,
        act_set = mlxsw_afa_block_first_set(rulei->act_block);
        mlxsw_reg_ptce2_flex_action_set_memcpy_to(ptce2_pl, act_set);
 
-       return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
+       err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptce2), ptce2_pl);
+       if (err)
+               goto err_ptce2_write;
+
+       return 0;
+
+err_ptce2_write:
+       cregion->ops->entry_remove(cregion, centry);
+       return err;
 }
 
 static void
index 1c19fee..2941967 100644 (file)
@@ -1022,7 +1022,6 @@ void mlxsw_sp_acl_erp_mask_put(struct mlxsw_sp_acl_atcam_region *aregion,
 {
        struct objagg_obj *objagg_obj = (struct objagg_obj *) erp_mask;
 
-       ASSERT_RTNL();
        objagg_obj_put(aregion->erp_table->objagg, objagg_obj);
 }
 
@@ -1054,7 +1053,6 @@ void mlxsw_sp_acl_erp_bf_remove(struct mlxsw_sp *mlxsw_sp,
        const struct mlxsw_sp_acl_erp *erp = objagg_obj_root_priv(objagg_obj);
        unsigned int erp_bank;
 
-       ASSERT_RTNL();
        if (!mlxsw_sp_acl_erp_table_is_used(erp->erp_table))
                return;
 
index 055cc69..9d9aa28 100644 (file)
@@ -997,8 +997,8 @@ static const struct mlxsw_sp_fid_ops mlxsw_sp_fid_dummy_ops = {
 static const struct mlxsw_sp_fid_family mlxsw_sp_fid_dummy_family = {
        .type                   = MLXSW_SP_FID_TYPE_DUMMY,
        .fid_size               = sizeof(struct mlxsw_sp_fid),
-       .start_index            = MLXSW_SP_RFID_BASE - 1,
-       .end_index              = MLXSW_SP_RFID_BASE - 1,
+       .start_index            = VLAN_N_VID - 1,
+       .end_index              = VLAN_N_VID - 1,
        .ops                    = &mlxsw_sp_fid_dummy_ops,
 };
 
index 0a31fff..fb1c48c 100644 (file)
@@ -816,14 +816,14 @@ int mlxsw_sp_nve_fid_enable(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp_fid *fid,
        ops = nve->nve_ops_arr[params->type];
 
        if (!ops->can_offload(nve, params->dev, extack))
-               return -EOPNOTSUPP;
+               return -EINVAL;
 
        memset(&config, 0, sizeof(config));
        ops->nve_config(nve, params->dev, &config);
        if (nve->num_nve_tunnels &&
            memcmp(&config, &nve->config, sizeof(config))) {
                NL_SET_ERR_MSG_MOD(extack, "Conflicting NVE tunnels configuration");
-               return -EOPNOTSUPP;
+               return -EINVAL;
        }
 
        err = mlxsw_sp_nve_tunnel_init(mlxsw_sp, &config);
index 1bd2c6e..c772109 100644 (file)
@@ -1078,8 +1078,7 @@ static int
 mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
                              struct mlxsw_sp_bridge_port *bridge_port,
                              u16 vid, bool is_untagged, bool is_pvid,
-                             struct netlink_ext_ack *extack,
-                             struct switchdev_trans *trans)
+                             struct netlink_ext_ack *extack)
 {
        u16 pvid = mlxsw_sp_port_pvid_determine(mlxsw_sp_port, vid, is_pvid);
        struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
@@ -1095,9 +1094,6 @@ mlxsw_sp_bridge_port_vlan_add(struct mlxsw_sp_port *mlxsw_sp_port,
            mlxsw_sp_port_vlan->bridge_port != bridge_port)
                return -EEXIST;
 
-       if (switchdev_trans_ph_prepare(trans))
-               return 0;
-
        if (!mlxsw_sp_port_vlan) {
                mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_create(mlxsw_sp_port,
                                                               vid);
@@ -1188,6 +1184,9 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
                return err;
        }
 
+       if (switchdev_trans_ph_commit(trans))
+               return 0;
+
        bridge_port = mlxsw_sp_bridge_port_find(mlxsw_sp->bridge, orig_dev);
        if (WARN_ON(!bridge_port))
                return -EINVAL;
@@ -1200,7 +1199,7 @@ static int mlxsw_sp_port_vlans_add(struct mlxsw_sp_port *mlxsw_sp_port,
 
                err = mlxsw_sp_bridge_port_vlan_add(mlxsw_sp_port, bridge_port,
                                                    vid, flag_untagged,
-                                                   flag_pvid, extack, trans);
+                                                   flag_pvid, extack);
                if (err)
                        return err;
        }
@@ -1234,7 +1233,7 @@ mlxsw_sp_bridge_port_fdb_flush(struct mlxsw_sp *mlxsw_sp,
 static enum mlxsw_reg_sfd_rec_policy mlxsw_sp_sfd_rec_policy(bool dynamic)
 {
        return dynamic ? MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_INGRESS :
-                        MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY;
+                        MLXSW_REG_SFD_REC_POLICY_DYNAMIC_ENTRY_MLAG;
 }
 
 static enum mlxsw_reg_sfd_op mlxsw_sp_sfd_op(bool adding)
@@ -1291,7 +1290,7 @@ out:
 static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
                                     const char *mac, u16 fid, bool adding,
                                     enum mlxsw_reg_sfd_rec_action action,
-                                    bool dynamic)
+                                    enum mlxsw_reg_sfd_rec_policy policy)
 {
        char *sfd_pl;
        u8 num_rec;
@@ -1302,8 +1301,7 @@ static int __mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
                return -ENOMEM;
 
        mlxsw_reg_sfd_pack(sfd_pl, mlxsw_sp_sfd_op(adding), 0);
-       mlxsw_reg_sfd_uc_pack(sfd_pl, 0, mlxsw_sp_sfd_rec_policy(dynamic),
-                             mac, fid, action, local_port);
+       mlxsw_reg_sfd_uc_pack(sfd_pl, 0, policy, mac, fid, action, local_port);
        num_rec = mlxsw_reg_sfd_num_rec_get(sfd_pl);
        err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(sfd), sfd_pl);
        if (err)
@@ -1322,7 +1320,8 @@ static int mlxsw_sp_port_fdb_uc_op(struct mlxsw_sp *mlxsw_sp, u8 local_port,
                                   bool dynamic)
 {
        return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, local_port, mac, fid, adding,
-                                        MLXSW_REG_SFD_REC_ACTION_NOP, dynamic);
+                                        MLXSW_REG_SFD_REC_ACTION_NOP,
+                                        mlxsw_sp_sfd_rec_policy(dynamic));
 }
 
 int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid,
@@ -1330,7 +1329,7 @@ int mlxsw_sp_rif_fdb_op(struct mlxsw_sp *mlxsw_sp, const char *mac, u16 fid,
 {
        return __mlxsw_sp_port_fdb_uc_op(mlxsw_sp, 0, mac, fid, adding,
                                         MLXSW_REG_SFD_REC_ACTION_FORWARD_IP_ROUTER,
-                                        false);
+                                        MLXSW_REG_SFD_REC_POLICY_STATIC_ENTRY);
 }
 
 static int mlxsw_sp_port_fdb_uc_lag_op(struct mlxsw_sp *mlxsw_sp, u16 lag_id,
@@ -1808,7 +1807,7 @@ static void
 mlxsw_sp_bridge_port_vlan_del(struct mlxsw_sp_port *mlxsw_sp_port,
                              struct mlxsw_sp_bridge_port *bridge_port, u16 vid)
 {
-       u16 pvid = mlxsw_sp_port->pvid == vid ? 0 : vid;
+       u16 pvid = mlxsw_sp_port->pvid == vid ? 0 : mlxsw_sp_port->pvid;
        struct mlxsw_sp_port_vlan *mlxsw_sp_port_vlan;
 
        mlxsw_sp_port_vlan = mlxsw_sp_port_vlan_find_by_vid(mlxsw_sp_port, vid);
@@ -3207,7 +3206,6 @@ mlxsw_sp_switchdev_vxlan_vlan_add(struct mlxsw_sp *mlxsw_sp,
                                  struct mlxsw_sp_bridge_device *bridge_device,
                                  const struct net_device *vxlan_dev, u16 vid,
                                  bool flag_untagged, bool flag_pvid,
-                                 struct switchdev_trans *trans,
                                  struct netlink_ext_ack *extack)
 {
        struct vxlan_dev *vxlan = netdev_priv(vxlan_dev);
@@ -3225,9 +3223,6 @@ mlxsw_sp_switchdev_vxlan_vlan_add(struct mlxsw_sp *mlxsw_sp,
            mlxsw_sp_bridge_8021q_vxlan_dev_find(bridge_device->dev, vid))
                return -EINVAL;
 
-       if (switchdev_trans_ph_prepare(trans))
-               return 0;
-
        if (!netif_running(vxlan_dev))
                return 0;
 
@@ -3345,6 +3340,9 @@ mlxsw_sp_switchdev_vxlan_vlans_add(struct net_device *vxlan_dev,
 
        port_obj_info->handled = true;
 
+       if (switchdev_trans_ph_commit(trans))
+               return 0;
+
        bridge_device = mlxsw_sp_bridge_device_find(mlxsw_sp->bridge, br_dev);
        if (!bridge_device)
                return -EINVAL;
@@ -3358,8 +3356,7 @@ mlxsw_sp_switchdev_vxlan_vlans_add(struct net_device *vxlan_dev,
                err = mlxsw_sp_switchdev_vxlan_vlan_add(mlxsw_sp, bridge_device,
                                                        vxlan_dev, vid,
                                                        flag_untagged,
-                                                       flag_pvid, trans,
-                                                       extack);
+                                                       flag_pvid, extack);
                if (err)
                        return err;
        }
index 20c9377..310807e 100644 (file)
@@ -962,13 +962,10 @@ static void lan743x_phy_link_status_change(struct net_device *netdev)
 
                memset(&ksettings, 0, sizeof(ksettings));
                phy_ethtool_get_link_ksettings(netdev, &ksettings);
-               local_advertisement = phy_read(phydev, MII_ADVERTISE);
-               if (local_advertisement < 0)
-                       return;
-
-               remote_advertisement = phy_read(phydev, MII_LPA);
-               if (remote_advertisement < 0)
-                       return;
+               local_advertisement =
+                       linkmode_adv_to_mii_adv_t(phydev->advertising);
+               remote_advertisement =
+                       linkmode_adv_to_mii_adv_t(phydev->lp_advertising);
 
                lan743x_phy_update_flowcontrol(adapter,
                                               ksettings.base.duplex,
index 5f384f7..19ce0e6 100644 (file)
@@ -3604,9 +3604,9 @@ static int myri10ge_alloc_slices(struct myri10ge_priv *mgp)
        for (i = 0; i < mgp->num_slices; i++) {
                ss = &mgp->ss[i];
                bytes = mgp->max_intr_slots * sizeof(*ss->rx_done.entry);
-               ss->rx_done.entry = dma_zalloc_coherent(&pdev->dev, bytes,
-                                                       &ss->rx_done.bus,
-                                                       GFP_KERNEL);
+               ss->rx_done.entry = dma_alloc_coherent(&pdev->dev, bytes,
+                                                      &ss->rx_done.bus,
+                                                      GFP_KERNEL);
                if (ss->rx_done.entry == NULL)
                        goto abort;
                bytes = sizeof(*ss->fw_stats);
index e23ca90..0a868c8 100644 (file)
@@ -1291,15 +1291,10 @@ wrp_alu64_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
 
 static int
 wrp_alu32_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta,
-             enum alu_op alu_op, bool skip)
+             enum alu_op alu_op)
 {
        const struct bpf_insn *insn = &meta->insn;
 
-       if (skip) {
-               meta->skip = true;
-               return 0;
-       }
-
        wrp_alu_imm(nfp_prog, insn->dst_reg * 2, alu_op, insn->imm);
        wrp_immed(nfp_prog, reg_both(insn->dst_reg * 2 + 1), 0);
 
@@ -2309,7 +2304,7 @@ static int xor_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 
 static int xor_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 {
-       return wrp_alu32_imm(nfp_prog, meta, ALU_OP_XOR, !~meta->insn.imm);
+       return wrp_alu32_imm(nfp_prog, meta, ALU_OP_XOR);
 }
 
 static int and_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
@@ -2319,7 +2314,7 @@ static int and_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 
 static int and_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 {
-       return wrp_alu32_imm(nfp_prog, meta, ALU_OP_AND, !~meta->insn.imm);
+       return wrp_alu32_imm(nfp_prog, meta, ALU_OP_AND);
 }
 
 static int or_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
@@ -2329,7 +2324,7 @@ static int or_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 
 static int or_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 {
-       return wrp_alu32_imm(nfp_prog, meta, ALU_OP_OR, !meta->insn.imm);
+       return wrp_alu32_imm(nfp_prog, meta, ALU_OP_OR);
 }
 
 static int add_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
@@ -2339,7 +2334,7 @@ static int add_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 
 static int add_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 {
-       return wrp_alu32_imm(nfp_prog, meta, ALU_OP_ADD, !meta->insn.imm);
+       return wrp_alu32_imm(nfp_prog, meta, ALU_OP_ADD);
 }
 
 static int sub_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
@@ -2349,7 +2344,7 @@ static int sub_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 
 static int sub_imm(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
 {
-       return wrp_alu32_imm(nfp_prog, meta, ALU_OP_SUB, !meta->insn.imm);
+       return wrp_alu32_imm(nfp_prog, meta, ALU_OP_SUB);
 }
 
 static int mul_reg(struct nfp_prog *nfp_prog, struct nfp_insn_meta *meta)
index e97636d..7d2d424 100644 (file)
@@ -2170,9 +2170,9 @@ nfp_net_tx_ring_alloc(struct nfp_net_dp *dp, struct nfp_net_tx_ring *tx_ring)
        tx_ring->cnt = dp->txd_cnt;
 
        tx_ring->size = array_size(tx_ring->cnt, sizeof(*tx_ring->txds));
-       tx_ring->txds = dma_zalloc_coherent(dp->dev, tx_ring->size,
-                                           &tx_ring->dma,
-                                           GFP_KERNEL | __GFP_NOWARN);
+       tx_ring->txds = dma_alloc_coherent(dp->dev, tx_ring->size,
+                                          &tx_ring->dma,
+                                          GFP_KERNEL | __GFP_NOWARN);
        if (!tx_ring->txds) {
                netdev_warn(dp->netdev, "failed to allocate TX descriptor ring memory, requested descriptor count: %d, consider lowering descriptor count\n",
                            tx_ring->cnt);
@@ -2328,9 +2328,9 @@ nfp_net_rx_ring_alloc(struct nfp_net_dp *dp, struct nfp_net_rx_ring *rx_ring)
 
        rx_ring->cnt = dp->rxd_cnt;
        rx_ring->size = array_size(rx_ring->cnt, sizeof(*rx_ring->rxds));
-       rx_ring->rxds = dma_zalloc_coherent(dp->dev, rx_ring->size,
-                                           &rx_ring->dma,
-                                           GFP_KERNEL | __GFP_NOWARN);
+       rx_ring->rxds = dma_alloc_coherent(dp->dev, rx_ring->size,
+                                          &rx_ring->dma,
+                                          GFP_KERNEL | __GFP_NOWARN);
        if (!rx_ring->rxds) {
                netdev_warn(dp->netdev, "failed to allocate RX descriptor ring memory, requested descriptor count: %d, consider lowering descriptor count\n",
                            rx_ring->cnt);
index 0611f23..1e408d1 100644 (file)
@@ -287,9 +287,9 @@ static int nixge_hw_dma_bd_init(struct net_device *ndev)
        priv->rx_bd_ci = 0;
 
        /* Allocate the Tx and Rx buffer descriptors. */
-       priv->tx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
-                                           sizeof(*priv->tx_bd_v) * TX_BD_NUM,
-                                           &priv->tx_bd_p, GFP_KERNEL);
+       priv->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+                                          sizeof(*priv->tx_bd_v) * TX_BD_NUM,
+                                          &priv->tx_bd_p, GFP_KERNEL);
        if (!priv->tx_bd_v)
                goto out;
 
@@ -299,9 +299,9 @@ static int nixge_hw_dma_bd_init(struct net_device *ndev)
        if (!priv->tx_skb)
                goto out;
 
-       priv->rx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
-                                           sizeof(*priv->rx_bd_v) * RX_BD_NUM,
-                                           &priv->rx_bd_p, GFP_KERNEL);
+       priv->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+                                          sizeof(*priv->rx_bd_v) * RX_BD_NUM,
+                                          &priv->rx_bd_p, GFP_KERNEL);
        if (!priv->rx_bd_v)
                goto out;
 
index 43c0c10..552d930 100644 (file)
@@ -1440,8 +1440,8 @@ pch_gbe_alloc_rx_buffers_pool(struct pch_gbe_adapter *adapter,
 
        size = rx_ring->count * bufsz + PCH_GBE_RESERVE_MEMORY;
        rx_ring->rx_buff_pool =
-               dma_zalloc_coherent(&pdev->dev, size,
-                                   &rx_ring->rx_buff_pool_logic, GFP_KERNEL);
+               dma_alloc_coherent(&pdev->dev, size,
+                                  &rx_ring->rx_buff_pool_logic, GFP_KERNEL);
        if (!rx_ring->rx_buff_pool)
                return -ENOMEM;
 
@@ -1755,8 +1755,8 @@ int pch_gbe_setup_tx_resources(struct pch_gbe_adapter *adapter,
 
        tx_ring->size = tx_ring->count * (int)sizeof(struct pch_gbe_tx_desc);
 
-       tx_ring->desc = dma_zalloc_coherent(&pdev->dev, tx_ring->size,
-                                           &tx_ring->dma, GFP_KERNEL);
+       tx_ring->desc = dma_alloc_coherent(&pdev->dev, tx_ring->size,
+                                          &tx_ring->dma, GFP_KERNEL);
        if (!tx_ring->desc) {
                vfree(tx_ring->buffer_info);
                return -ENOMEM;
@@ -1798,8 +1798,8 @@ int pch_gbe_setup_rx_resources(struct pch_gbe_adapter *adapter,
                return -ENOMEM;
 
        rx_ring->size = rx_ring->count * (int)sizeof(struct pch_gbe_rx_desc);
-       rx_ring->desc = dma_zalloc_coherent(&pdev->dev, rx_ring->size,
-                                           &rx_ring->dma, GFP_KERNEL);
+       rx_ring->desc = dma_alloc_coherent(&pdev->dev, rx_ring->size,
+                                                 &rx_ring->dma, GFP_KERNEL);
        if (!rx_ring->desc) {
                vfree(rx_ring->buffer_info);
                return -ENOMEM;
index 8a31a02..d210415 100644 (file)
@@ -401,9 +401,9 @@ static int pasemi_mac_setup_rx_resources(const struct net_device *dev)
        if (pasemi_dma_alloc_ring(&ring->chan, RX_RING_SIZE))
                goto out_ring_desc;
 
-       ring->buffers = dma_zalloc_coherent(&mac->dma_pdev->dev,
-                                           RX_RING_SIZE * sizeof(u64),
-                                           &ring->buf_dma, GFP_KERNEL);
+       ring->buffers = dma_alloc_coherent(&mac->dma_pdev->dev,
+                                          RX_RING_SIZE * sizeof(u64),
+                                          &ring->buf_dma, GFP_KERNEL);
        if (!ring->buffers)
                goto out_ring_desc;
 
index 24a9016..2d8a77c 100644 (file)
@@ -53,7 +53,7 @@
 extern const struct qed_common_ops qed_common_ops_pass;
 
 #define QED_MAJOR_VERSION              8
-#define QED_MINOR_VERSION              33
+#define QED_MINOR_VERSION              37
 #define QED_REVISION_VERSION           0
 #define QED_ENGINEERING_VERSION                20
 
index dc1c1b6..c2ad405 100644 (file)
@@ -936,9 +936,9 @@ static int qed_cxt_src_t2_alloc(struct qed_hwfn *p_hwfn)
                u32 size = min_t(u32, total_size, psz);
                void **p_virt = &p_mngr->t2[i].p_virt;
 
-               *p_virt = dma_zalloc_coherent(&p_hwfn->cdev->pdev->dev,
-                                             size, &p_mngr->t2[i].p_phys,
-                                             GFP_KERNEL);
+               *p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, size,
+                                            &p_mngr->t2[i].p_phys,
+                                            GFP_KERNEL);
                if (!p_mngr->t2[i].p_virt) {
                        rc = -ENOMEM;
                        goto t2_fail;
@@ -1054,8 +1054,8 @@ static int qed_ilt_blk_alloc(struct qed_hwfn *p_hwfn,
                u32 size;
 
                size = min_t(u32, sz_left, p_blk->real_size_in_page);
-               p_virt = dma_zalloc_coherent(&p_hwfn->cdev->pdev->dev, size,
-                                            &p_phys, GFP_KERNEL);
+               p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev, size,
+                                           &p_phys, GFP_KERNEL);
                if (!p_virt)
                        return -ENOMEM;
 
@@ -2306,9 +2306,9 @@ qed_cxt_dynamic_ilt_alloc(struct qed_hwfn *p_hwfn,
                goto out0;
        }
 
-       p_virt = dma_zalloc_coherent(&p_hwfn->cdev->pdev->dev,
-                                    p_blk->real_size_in_page, &p_phys,
-                                    GFP_KERNEL);
+       p_virt = dma_alloc_coherent(&p_hwfn->cdev->pdev->dev,
+                                   p_blk->real_size_in_page, &p_phys,
+                                   GFP_KERNEL);
        if (!p_virt) {
                rc = -ENOMEM;
                goto out1;
index 8f65514..2ecaaaa 100644 (file)
@@ -795,19 +795,19 @@ static void qed_init_qm_pq(struct qed_hwfn *p_hwfn,
 
 /* get pq index according to PQ_FLAGS */
 static u16 *qed_init_qm_get_idx_from_flags(struct qed_hwfn *p_hwfn,
-                                          u32 pq_flags)
+                                          unsigned long pq_flags)
 {
        struct qed_qm_info *qm_info = &p_hwfn->qm_info;
 
        /* Can't have multiple flags set here */
-       if (bitmap_weight((unsigned long *)&pq_flags,
+       if (bitmap_weight(&pq_flags,
                          sizeof(pq_flags) * BITS_PER_BYTE) > 1) {
-               DP_ERR(p_hwfn, "requested multiple pq flags 0x%x\n", pq_flags);
+               DP_ERR(p_hwfn, "requested multiple pq flags 0x%lx\n", pq_flags);
                goto err;
        }
 
        if (!(qed_get_pq_flags(p_hwfn) & pq_flags)) {
-               DP_ERR(p_hwfn, "pq flag 0x%x is not set\n", pq_flags);
+               DP_ERR(p_hwfn, "pq flag 0x%lx is not set\n", pq_flags);
                goto err;
        }
 
index beb8e5d..ded556b 100644 (file)
@@ -1688,6 +1688,15 @@ qed_iwarp_parse_rx_pkt(struct qed_hwfn *p_hwfn,
 
        eth_hlen = ETH_HLEN + (vlan_valid ? sizeof(u32) : 0);
 
+       if (!ether_addr_equal(ethh->h_dest,
+                             p_hwfn->p_rdma_info->iwarp.mac_addr)) {
+               DP_VERBOSE(p_hwfn,
+                          QED_MSG_RDMA,
+                          "Got unexpected mac %pM instead of %pM\n",
+                          ethh->h_dest, p_hwfn->p_rdma_info->iwarp.mac_addr);
+               return -EINVAL;
+       }
+
        ether_addr_copy(remote_mac_addr, ethh->h_source);
        ether_addr_copy(local_mac_addr, ethh->h_dest);
 
@@ -2605,7 +2614,7 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn,
        struct qed_iwarp_info *iwarp_info;
        struct qed_ll2_acquire_data data;
        struct qed_ll2_cbs cbs;
-       u32 mpa_buff_size;
+       u32 buff_size;
        u16 n_ooo_bufs;
        int rc = 0;
        int i;
@@ -2632,7 +2641,7 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn,
 
        memset(&data, 0, sizeof(data));
        data.input.conn_type = QED_LL2_TYPE_IWARP;
-       data.input.mtu = QED_IWARP_MAX_SYN_PKT_SIZE;
+       data.input.mtu = params->max_mtu;
        data.input.rx_num_desc = QED_IWARP_LL2_SYN_RX_SIZE;
        data.input.tx_num_desc = QED_IWARP_LL2_SYN_TX_SIZE;
        data.input.tx_max_bds_per_packet = 1;   /* will never be fragmented */
@@ -2654,9 +2663,10 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn,
                goto err;
        }
 
+       buff_size = QED_IWARP_MAX_BUF_SIZE(params->max_mtu);
        rc = qed_iwarp_ll2_alloc_buffers(p_hwfn,
                                         QED_IWARP_LL2_SYN_RX_SIZE,
-                                        QED_IWARP_MAX_SYN_PKT_SIZE,
+                                        buff_size,
                                         iwarp_info->ll2_syn_handle);
        if (rc)
                goto err;
@@ -2710,10 +2720,9 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn,
        if (rc)
                goto err;
 
-       mpa_buff_size = QED_IWARP_MAX_BUF_SIZE(params->max_mtu);
        rc = qed_iwarp_ll2_alloc_buffers(p_hwfn,
                                         data.input.rx_num_desc,
-                                        mpa_buff_size,
+                                        buff_size,
                                         iwarp_info->ll2_mpa_handle);
        if (rc)
                goto err;
@@ -2726,7 +2735,7 @@ qed_iwarp_ll2_start(struct qed_hwfn *p_hwfn,
 
        iwarp_info->max_num_partial_fpdus = (u16)p_hwfn->p_rdma_info->num_qps;
 
-       iwarp_info->mpa_intermediate_buf = kzalloc(mpa_buff_size, GFP_KERNEL);
+       iwarp_info->mpa_intermediate_buf = kzalloc(buff_size, GFP_KERNEL);
        if (!iwarp_info->mpa_intermediate_buf)
                goto err;
 
index b8f612d..7ac9590 100644 (file)
@@ -46,7 +46,6 @@ enum qed_iwarp_qp_state qed_roce2iwarp_state(enum qed_roce_qp_state state);
 
 #define QED_IWARP_LL2_SYN_TX_SIZE       (128)
 #define QED_IWARP_LL2_SYN_RX_SIZE       (256)
-#define QED_IWARP_MAX_SYN_PKT_SIZE      (128)
 
 #define QED_IWARP_LL2_OOO_DEF_TX_SIZE   (256)
 #define QED_IWARP_MAX_OOO              (16)
index 67c02ea..58be1c4 100644 (file)
@@ -609,6 +609,10 @@ qed_sp_update_accept_mode(struct qed_hwfn *p_hwfn,
                          (!!(accept_filter & QED_ACCEPT_MCAST_MATCHED) &&
                           !!(accept_filter & QED_ACCEPT_MCAST_UNMATCHED)));
 
+               SET_FIELD(state, ETH_VPORT_TX_MODE_UCAST_ACCEPT_ALL,
+                         (!!(accept_filter & QED_ACCEPT_UCAST_MATCHED) &&
+                          !!(accept_filter & QED_ACCEPT_UCAST_UNMATCHED)));
+
                SET_FIELD(state, ETH_VPORT_TX_MODE_BCAST_ACCEPT_ALL,
                          !!(accept_filter & QED_ACCEPT_BCAST));
 
@@ -744,6 +748,11 @@ int qed_sp_vport_update(struct qed_hwfn *p_hwfn,
                return rc;
        }
 
+       if (p_params->update_ctl_frame_check) {
+               p_cmn->ctl_frame_mac_check_en = p_params->mac_chk_en;
+               p_cmn->ctl_frame_ethtype_check_en = p_params->ethtype_chk_en;
+       }
+
        /* Update mcast bins for VFs, PF doesn't use this functionality */
        qed_sp_update_mcast_bin(p_hwfn, p_ramrod, p_params);
 
@@ -2207,7 +2216,7 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
                        u16 num_queues = 0;
 
                        /* Since the feature controls only queue-zones,
-                        * make sure we have the contexts [rx, tx, xdp] to
+                        * make sure we have the contexts [rx, xdp, tcs] to
                         * match.
                         */
                        for_each_hwfn(cdev, i) {
@@ -2217,7 +2226,8 @@ static int qed_fill_eth_dev_info(struct qed_dev *cdev,
                                u16 cids;
 
                                cids = hwfn->pf_params.eth_pf_params.num_cons;
-                               num_queues += min_t(u16, l2_queues, cids / 3);
+                               cids /= (2 + info->num_tc);
+                               num_queues += min_t(u16, l2_queues, cids);
                        }
 
                        /* queues might theoretically be >256, but interrupts'
@@ -2688,7 +2698,8 @@ static int qed_configure_filter_rx_mode(struct qed_dev *cdev,
        if (type == QED_FILTER_RX_MODE_TYPE_PROMISC) {
                accept_flags.rx_accept_filter |= QED_ACCEPT_UCAST_UNMATCHED |
                                                 QED_ACCEPT_MCAST_UNMATCHED;
-               accept_flags.tx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED;
+               accept_flags.tx_accept_filter |= QED_ACCEPT_UCAST_UNMATCHED |
+                                                QED_ACCEPT_MCAST_UNMATCHED;
        } else if (type == QED_FILTER_RX_MODE_TYPE_MULTI_PROMISC) {
                accept_flags.rx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED;
                accept_flags.tx_accept_filter |= QED_ACCEPT_MCAST_UNMATCHED;
@@ -2860,7 +2871,8 @@ static int qed_get_coalesce(struct qed_dev *cdev, u16 *coal, void *handle)
        p_hwfn = p_cid->p_owner;
        rc = qed_get_queue_coalesce(p_hwfn, coal, handle);
        if (rc)
-               DP_NOTICE(p_hwfn, "Unable to read queue coalescing\n");
+               DP_VERBOSE(cdev, QED_MSG_DEBUG,
+                          "Unable to read queue coalescing\n");
 
        return rc;
 }
index 8d80f10..7127d5a 100644 (file)
@@ -219,6 +219,9 @@ struct qed_sp_vport_update_params {
        struct qed_rss_params           *rss_params;
        struct qed_filter_accept_flags  accept_flags;
        struct qed_sge_tpa_params       *sge_tpa_params;
+       u8                              update_ctl_frame_check;
+       u8                              mac_chk_en;
+       u8                              ethtype_chk_en;
 };
 
 int qed_sp_vport_update(struct qed_hwfn *p_hwfn,
index 90afd51..b5f419b 100644 (file)
@@ -1619,6 +1619,10 @@ static void qed_ll2_post_rx_buffer_notify_fw(struct qed_hwfn *p_hwfn,
        cq_prod = qed_chain_get_prod_idx(&p_rx->rcq_chain);
        rx_prod.bd_prod = cpu_to_le16(bd_prod);
        rx_prod.cqe_prod = cpu_to_le16(cq_prod);
+
+       /* Make sure chain element is updated before ringing the doorbell */
+       dma_wmb();
+
        DIRECT_REG_WR(p_rx->set_prod_addr, *((u32 *)&rx_prod));
 }
 
@@ -2447,19 +2451,24 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb,
 {
        struct qed_ll2_tx_pkt_info pkt;
        const skb_frag_t *frag;
+       u8 flags = 0, nr_frags;
        int rc = -EINVAL, i;
        dma_addr_t mapping;
        u16 vlan = 0;
-       u8 flags = 0;
 
        if (unlikely(skb->ip_summed != CHECKSUM_NONE)) {
                DP_INFO(cdev, "Cannot transmit a checksummed packet\n");
                return -EINVAL;
        }
 
-       if (1 + skb_shinfo(skb)->nr_frags > CORE_LL2_TX_MAX_BDS_PER_PACKET) {
+       /* Cache number of fragments from SKB since SKB may be freed by
+        * the completion routine after calling qed_ll2_prepare_tx_packet()
+        */
+       nr_frags = skb_shinfo(skb)->nr_frags;
+
+       if (1 + nr_frags > CORE_LL2_TX_MAX_BDS_PER_PACKET) {
                DP_ERR(cdev, "Cannot transmit a packet with %d fragments\n",
-                      1 + skb_shinfo(skb)->nr_frags);
+                      1 + nr_frags);
                return -EINVAL;
        }
 
@@ -2481,7 +2490,7 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb,
        }
 
        memset(&pkt, 0, sizeof(pkt));
-       pkt.num_of_bds = 1 + skb_shinfo(skb)->nr_frags;
+       pkt.num_of_bds = 1 + nr_frags;
        pkt.vlan = vlan;
        pkt.bd_flags = flags;
        pkt.tx_dest = QED_LL2_TX_DEST_NW;
@@ -2492,12 +2501,17 @@ static int qed_ll2_start_xmit(struct qed_dev *cdev, struct sk_buff *skb,
            test_bit(QED_LL2_XMIT_FLAGS_FIP_DISCOVERY, &xmit_flags))
                pkt.remove_stag = true;
 
+       /* qed_ll2_prepare_tx_packet() may actually send the packet if
+        * there are no fragments in the skb and subsequently the completion
+        * routine may run and free the SKB, so no dereferencing the SKB
+        * beyond this point unless skb has any fragments.
+        */
        rc = qed_ll2_prepare_tx_packet(&cdev->hwfns[0], cdev->ll2->handle,
                                       &pkt, 1);
        if (rc)
                goto err;
 
-       for (i = 0; i < skb_shinfo(skb)->nr_frags; i++) {
+       for (i = 0; i < nr_frags; i++) {
                frag = &skb_shinfo(skb)->frags[i];
 
                mapping = skb_frag_dma_map(&cdev->pdev->dev, frag, 0,
index 4179c90..96ab77a 100644 (file)
@@ -382,6 +382,7 @@ void qed_consq_setup(struct qed_hwfn *p_hwfn);
  * @param p_hwfn
  */
 void qed_consq_free(struct qed_hwfn *p_hwfn);
+int qed_spq_pend_post(struct qed_hwfn *p_hwfn);
 
 /**
  * @file
index 888274f..5a495fd 100644 (file)
@@ -604,6 +604,9 @@ int qed_sp_pf_update_stag(struct qed_hwfn *p_hwfn)
 
        p_ent->ramrod.pf_update.update_mf_vlan_flag = true;
        p_ent->ramrod.pf_update.mf_vlan = cpu_to_le16(p_hwfn->hw_info.ovlan);
+       if (test_bit(QED_MF_UFP_SPECIFIC, &p_hwfn->cdev->mf_bits))
+               p_ent->ramrod.pf_update.mf_vlan |=
+                       cpu_to_le16(((u16)p_hwfn->ufp_info.tc << 13));
 
        return qed_spq_post(p_hwfn, p_ent, NULL);
 }
index eb88bbc..ba64ff9 100644 (file)
@@ -397,6 +397,11 @@ int qed_eq_completion(struct qed_hwfn *p_hwfn, void *cookie)
 
        qed_eq_prod_update(p_hwfn, qed_chain_get_prod_idx(p_chain));
 
+       /* Attempt to post pending requests */
+       spin_lock_bh(&p_hwfn->p_spq->lock);
+       rc = qed_spq_pend_post(p_hwfn);
+       spin_unlock_bh(&p_hwfn->p_spq->lock);
+
        return rc;
 }
 
@@ -767,7 +772,7 @@ static int qed_spq_post_list(struct qed_hwfn *p_hwfn,
        return 0;
 }
 
-static int qed_spq_pend_post(struct qed_hwfn *p_hwfn)
+int qed_spq_pend_post(struct qed_hwfn *p_hwfn)
 {
        struct qed_spq *p_spq = p_hwfn->p_spq;
        struct qed_spq_entry *p_ent = NULL;
@@ -905,7 +910,6 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn,
        struct qed_spq_entry    *p_ent = NULL;
        struct qed_spq_entry    *tmp;
        struct qed_spq_entry    *found = NULL;
-       int                     rc;
 
        if (!p_hwfn)
                return -EINVAL;
@@ -963,12 +967,7 @@ int qed_spq_completion(struct qed_hwfn *p_hwfn,
                 */
                qed_spq_return_entry(p_hwfn, found);
 
-       /* Attempt to post pending requests */
-       spin_lock_bh(&p_spq->lock);
-       rc = qed_spq_pend_post(p_hwfn);
-       spin_unlock_bh(&p_spq->lock);
-
-       return rc;
+       return 0;
 }
 
 int qed_consq_alloc(struct qed_hwfn *p_hwfn)
index ca6290f..71a7af1 100644 (file)
@@ -1969,7 +1969,9 @@ static void qed_iov_vf_mbx_start_vport(struct qed_hwfn *p_hwfn,
        params.vport_id = vf->vport_id;
        params.max_buffers_per_cqe = start->max_buffers_per_cqe;
        params.mtu = vf->mtu;
-       params.check_mac = true;
+
+       /* Non trusted VFs should enable control frame filtering */
+       params.check_mac = !vf->p_vf_info.is_trusted_configured;
 
        rc = qed_sp_eth_vport_start(p_hwfn, &params);
        if (rc) {
@@ -5130,6 +5132,9 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
                params.opaque_fid = vf->opaque_fid;
                params.vport_id = vf->vport_id;
 
+               params.update_ctl_frame_check = 1;
+               params.mac_chk_en = !vf_info->is_trusted_configured;
+
                if (vf_info->rx_accept_mode & mask) {
                        flags->update_rx_mode_config = 1;
                        flags->rx_accept_filter = vf_info->rx_accept_mode;
@@ -5147,7 +5152,8 @@ static void qed_iov_handle_trust_change(struct qed_hwfn *hwfn)
                }
 
                if (flags->update_rx_mode_config ||
-                   flags->update_tx_mode_config)
+                   flags->update_tx_mode_config ||
+                   params.update_ctl_frame_check)
                        qed_sp_vport_update(hwfn, &params,
                                            QED_SPQ_MODE_EBLOCK, NULL);
        }
index b6cccf4..5dda547 100644 (file)
@@ -261,6 +261,7 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
        struct pfvf_acquire_resp_tlv *resp = &p_iov->pf2vf_reply->acquire_resp;
        struct pf_vf_pfdev_info *pfdev_info = &resp->pfdev_info;
        struct vf_pf_resc_request *p_resc;
+       u8 retry_cnt = VF_ACQUIRE_THRESH;
        bool resources_acquired = false;
        struct vfpf_acquire_tlv *req;
        int rc = 0, attempts = 0;
@@ -314,6 +315,15 @@ static int qed_vf_pf_acquire(struct qed_hwfn *p_hwfn)
 
                /* send acquire request */
                rc = qed_send_msg2pf(p_hwfn, &resp->hdr.status, sizeof(*resp));
+
+               /* Re-try acquire in case of vf-pf hw channel timeout */
+               if (retry_cnt && rc == -EBUSY) {
+                       DP_VERBOSE(p_hwfn, QED_MSG_IOV,
+                                  "VF retrying to acquire due to VPC timeout\n");
+                       retry_cnt--;
+                       continue;
+               }
+
                if (rc)
                        goto exit;
 
index 613249d..730997b 100644 (file)
@@ -56,7 +56,7 @@
 #include <net/tc_act/tc_gact.h>
 
 #define QEDE_MAJOR_VERSION             8
-#define QEDE_MINOR_VERSION             33
+#define QEDE_MINOR_VERSION             37
 #define QEDE_REVISION_VERSION          0
 #define QEDE_ENGINEERING_VERSION       20
 #define DRV_MODULE_VERSION __stringify(QEDE_MAJOR_VERSION) "." \
@@ -494,6 +494,9 @@ struct qede_reload_args {
 
 /* Datapath functions definition */
 netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev);
+u16 qede_select_queue(struct net_device *dev, struct sk_buff *skb,
+                     struct net_device *sb_dev,
+                     select_queue_fallback_t fallback);
 netdev_features_t qede_features_check(struct sk_buff *skb,
                                      struct net_device *dev,
                                      netdev_features_t features);
index bdf816f..31b046e 100644 (file)
@@ -1695,6 +1695,19 @@ netdev_tx_t qede_start_xmit(struct sk_buff *skb, struct net_device *ndev)
        return NETDEV_TX_OK;
 }
 
+u16 qede_select_queue(struct net_device *dev, struct sk_buff *skb,
+                     struct net_device *sb_dev,
+                     select_queue_fallback_t fallback)
+{
+       struct qede_dev *edev = netdev_priv(dev);
+       int total_txq;
+
+       total_txq = QEDE_TSS_COUNT(edev) * edev->dev_info.num_tc;
+
+       return QEDE_TSS_COUNT(edev) ?
+               fallback(dev, skb, NULL) % total_txq :  0;
+}
+
 /* 8B udp header + 8B base tunnel header + 32B option length */
 #define QEDE_MAX_TUN_HDR_LEN 48
 
index 5a74fcb..9790f26 100644 (file)
@@ -631,6 +631,7 @@ static const struct net_device_ops qede_netdev_ops = {
        .ndo_open = qede_open,
        .ndo_stop = qede_close,
        .ndo_start_xmit = qede_start_xmit,
+       .ndo_select_queue = qede_select_queue,
        .ndo_set_rx_mode = qede_set_rx_mode,
        .ndo_set_mac_address = qede_set_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
@@ -666,6 +667,7 @@ static const struct net_device_ops qede_netdev_vf_ops = {
        .ndo_open = qede_open,
        .ndo_stop = qede_close,
        .ndo_start_xmit = qede_start_xmit,
+       .ndo_select_queue = qede_select_queue,
        .ndo_set_rx_mode = qede_set_rx_mode,
        .ndo_set_mac_address = qede_set_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
@@ -684,6 +686,7 @@ static const struct net_device_ops qede_netdev_vf_xdp_ops = {
        .ndo_open = qede_open,
        .ndo_stop = qede_close,
        .ndo_start_xmit = qede_start_xmit,
+       .ndo_select_queue = qede_select_queue,
        .ndo_set_rx_mode = qede_set_rx_mode,
        .ndo_set_mac_address = qede_set_mac_addr,
        .ndo_validate_addr = eth_validate_addr,
index d344e9d..af38d3d 100644 (file)
@@ -434,14 +434,14 @@ int qlcnic_82xx_fw_cmd_create_tx_ctx(struct qlcnic_adapter *adapter,
        *(tx_ring->hw_consumer) = 0;
 
        rq_size = SIZEOF_HOSTRQ_TX(struct qlcnic_hostrq_tx_ctx);
-       rq_addr = dma_zalloc_coherent(&adapter->pdev->dev, rq_size,
-                                     &rq_phys_addr, GFP_KERNEL);
+       rq_addr = dma_alloc_coherent(&adapter->pdev->dev, rq_size,
+                                    &rq_phys_addr, GFP_KERNEL);
        if (!rq_addr)
                return -ENOMEM;
 
        rsp_size = SIZEOF_CARDRSP_TX(struct qlcnic_cardrsp_tx_ctx);
-       rsp_addr = dma_zalloc_coherent(&adapter->pdev->dev, rsp_size,
-                                      &rsp_phys_addr, GFP_KERNEL);
+       rsp_addr = dma_alloc_coherent(&adapter->pdev->dev, rsp_size,
+                                     &rsp_phys_addr, GFP_KERNEL);
        if (!rsp_addr) {
                err = -ENOMEM;
                goto out_free_rq;
@@ -855,8 +855,8 @@ int qlcnic_82xx_get_nic_info(struct qlcnic_adapter *adapter,
        struct qlcnic_cmd_args cmd;
        size_t  nic_size = sizeof(struct qlcnic_info_le);
 
-       nic_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, nic_size,
-                                           &nic_dma_t, GFP_KERNEL);
+       nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
+                                          &nic_dma_t, GFP_KERNEL);
        if (!nic_info_addr)
                return -ENOMEM;
 
@@ -909,8 +909,8 @@ int qlcnic_82xx_set_nic_info(struct qlcnic_adapter *adapter,
        if (adapter->ahw->op_mode != QLCNIC_MGMT_FUNC)
                return err;
 
-       nic_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, nic_size,
-                                           &nic_dma_t, GFP_KERNEL);
+       nic_info_addr = dma_alloc_coherent(&adapter->pdev->dev, nic_size,
+                                          &nic_dma_t, GFP_KERNEL);
        if (!nic_info_addr)
                return -ENOMEM;
 
@@ -964,8 +964,8 @@ int qlcnic_82xx_get_pci_info(struct qlcnic_adapter *adapter,
        void *pci_info_addr;
        int err = 0, i;
 
-       pci_info_addr = dma_zalloc_coherent(&adapter->pdev->dev, pci_size,
-                                           &pci_info_dma_t, GFP_KERNEL);
+       pci_info_addr = dma_alloc_coherent(&adapter->pdev->dev, pci_size,
+                                          &pci_info_dma_t, GFP_KERNEL);
        if (!pci_info_addr)
                return -ENOMEM;
 
@@ -1078,8 +1078,8 @@ int qlcnic_get_port_stats(struct qlcnic_adapter *adapter, const u8 func,
                return -EIO;
        }
 
-       stats_addr = dma_zalloc_coherent(&adapter->pdev->dev, stats_size,
-                                        &stats_dma_t, GFP_KERNEL);
+       stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
+                                       &stats_dma_t, GFP_KERNEL);
        if (!stats_addr)
                return -ENOMEM;
 
@@ -1134,8 +1134,8 @@ int qlcnic_get_mac_stats(struct qlcnic_adapter *adapter,
        if (mac_stats == NULL)
                return -ENOMEM;
 
-       stats_addr = dma_zalloc_coherent(&adapter->pdev->dev, stats_size,
-                                        &stats_dma_t, GFP_KERNEL);
+       stats_addr = dma_alloc_coherent(&adapter->pdev->dev, stats_size,
+                                       &stats_dma_t, GFP_KERNEL);
        if (!stats_addr)
                return -ENOMEM;
 
index 031f6e6..8d79031 100644 (file)
@@ -776,7 +776,7 @@ int emac_mac_rx_tx_rings_alloc_all(struct emac_adapter *adpt)
                            8 + 2 * 8; /* 8 byte per one Tx and two Rx rings */
 
        ring_header->used = 0;
-       ring_header->v_addr = dma_zalloc_coherent(dev, ring_header->size,
+       ring_header->v_addr = dma_alloc_coherent(dev, ring_header->size,
                                                 &ring_header->dma_addr,
                                                 GFP_KERNEL);
        if (!ring_header->v_addr)
index 44f6e48..4f910c4 100644 (file)
@@ -691,7 +691,7 @@ static void cp_tx (struct cp_private *cp)
                        }
                        bytes_compl += skb->len;
                        pkts_compl++;
-                       dev_kfree_skb_irq(skb);
+                       dev_consume_skb_irq(skb);
                }
 
                cp->tx_skb[tx_tail] = NULL;
index 298930d..6e36b88 100644 (file)
@@ -205,6 +205,8 @@ enum cfg_version {
 };
 
 static const struct pci_device_id rtl8169_pci_tbl[] = {
+       { PCI_VDEVICE(REALTEK,  0x2502), RTL_CFG_1 },
+       { PCI_VDEVICE(REALTEK,  0x2600), RTL_CFG_1 },
        { PCI_VDEVICE(REALTEK,  0x8129), RTL_CFG_0 },
        { PCI_VDEVICE(REALTEK,  0x8136), RTL_CFG_2 },
        { PCI_VDEVICE(REALTEK,  0x8161), RTL_CFG_1 },
@@ -706,6 +708,7 @@ module_param(use_dac, int, 0);
 MODULE_PARM_DESC(use_dac, "Enable PCI DAC. Unsafe on 32 bit PCI slot.");
 module_param_named(debug, debug.msg_enable, int, 0);
 MODULE_PARM_DESC(debug, "Debug verbosity level (0=none, ..., 16=all)");
+MODULE_SOFTDEP("pre: realtek");
 MODULE_LICENSE("GPL");
 MODULE_FIRMWARE(FIRMWARE_8168D_1);
 MODULE_FIRMWARE(FIRMWARE_8168D_2);
@@ -1283,11 +1286,13 @@ static u16 rtl_get_events(struct rtl8169_private *tp)
 static void rtl_ack_events(struct rtl8169_private *tp, u16 bits)
 {
        RTL_W16(tp, IntrStatus, bits);
+       mmiowb();
 }
 
 static void rtl_irq_disable(struct rtl8169_private *tp)
 {
        RTL_W16(tp, IntrMask, 0);
+       mmiowb();
 }
 
 #define RTL_EVENT_NAPI_RX      (RxOK | RxErr)
@@ -1679,11 +1684,13 @@ static bool rtl8169_reset_counters(struct rtl8169_private *tp)
 
 static bool rtl8169_update_counters(struct rtl8169_private *tp)
 {
+       u8 val = RTL_R8(tp, ChipCmd);
+
        /*
         * Some chips are unable to dump tally counters when the receiver
-        * is disabled.
+        * is disabled. If 0xff chip may be in a PCI power-save state.
         */
-       if ((RTL_R8(tp, ChipCmd) & CmdRxEnb) == 0)
+       if (!(val & CmdRxEnb) || val == 0xff)
                return true;
 
        return rtl8169_do_counters(tp, CounterDump);
@@ -6067,7 +6074,6 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
        struct device *d = tp_to_dev(tp);
        dma_addr_t mapping;
        u32 opts[2], len;
-       bool stop_queue;
        int frags;
 
        if (unlikely(!rtl_tx_slots_avail(tp, skb_shinfo(skb)->nr_frags))) {
@@ -6109,6 +6115,8 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
 
        txd->opts2 = cpu_to_le32(opts[1]);
 
+       netdev_sent_queue(dev, skb->len);
+
        skb_tx_timestamp(skb);
 
        /* Force memory writes to complete before releasing descriptor */
@@ -6121,14 +6129,16 @@ static netdev_tx_t rtl8169_start_xmit(struct sk_buff *skb,
 
        tp->cur_tx += frags + 1;
 
-       stop_queue = !rtl_tx_slots_avail(tp, MAX_SKB_FRAGS);
-       if (unlikely(stop_queue))
-               netif_stop_queue(dev);
+       RTL_W8(tp, TxPoll, NPQ);
 
-       if (__netdev_sent_queue(dev, skb->len, skb->xmit_more))
-               RTL_W8(tp, TxPoll, NPQ);
+       mmiowb();
 
-       if (unlikely(stop_queue)) {
+       if (!rtl_tx_slots_avail(tp, MAX_SKB_FRAGS)) {
+               /* Avoid wrongly optimistic queue wake-up: rtl_tx thread must
+                * not miss a ring update when it notices a stopped queue.
+                */
+               smp_wmb();
+               netif_stop_queue(dev);
                /* Sync with rtl_tx:
                 * - publish queue status and cur_tx ring index (write barrier)
                 * - refresh dirty_tx ring index (read barrier).
@@ -6478,7 +6488,9 @@ static int rtl8169_poll(struct napi_struct *napi, int budget)
 
        if (work_done < budget) {
                napi_complete_done(napi, work_done);
+
                rtl_irq_enable(tp);
+               mmiowb();
        }
 
        return work_done;
index ffc1ada..d28c8f9 100644 (file)
@@ -343,7 +343,7 @@ static int ravb_ring_init(struct net_device *ndev, int q)
        int i;
 
        priv->rx_buf_sz = (ndev->mtu <= 1492 ? PKT_BUF_SZ : ndev->mtu) +
-               ETH_HLEN + VLAN_HLEN;
+               ETH_HLEN + VLAN_HLEN + sizeof(__sum16);
 
        /* Allocate RX and TX skb rings */
        priv->rx_skb[q] = kcalloc(priv->num_rx_ring[q],
@@ -524,13 +524,15 @@ static void ravb_rx_csum(struct sk_buff *skb)
 {
        u8 *hw_csum;
 
-       /* The hardware checksum is 2 bytes appended to packet data */
-       if (unlikely(skb->len < 2))
+       /* The hardware checksum is contained in sizeof(__sum16) (2) bytes
+        * appended to packet data
+        */
+       if (unlikely(skb->len < sizeof(__sum16)))
                return;
-       hw_csum = skb_tail_pointer(skb) - 2;
+       hw_csum = skb_tail_pointer(skb) - sizeof(__sum16);
        skb->csum = csum_unfold((__force __sum16)get_unaligned_le16(hw_csum));
        skb->ip_summed = CHECKSUM_COMPLETE;
-       skb_trim(skb, skb->len - 2);
+       skb_trim(skb, skb->len - sizeof(__sum16));
 }
 
 /* Packet receive function for Ethernet AVB */
index 690aee8..6d22dd5 100644 (file)
@@ -400,9 +400,9 @@ static int init_tx_ring(struct device *dev, u8 queue_no,
        }
 
        /* allocate memory for TX descriptors */
-       tx_ring->dma_tx = dma_zalloc_coherent(dev,
-                                             tx_rsize * sizeof(struct sxgbe_tx_norm_desc),
-                                             &tx_ring->dma_tx_phy, GFP_KERNEL);
+       tx_ring->dma_tx = dma_alloc_coherent(dev,
+                                            tx_rsize * sizeof(struct sxgbe_tx_norm_desc),
+                                            &tx_ring->dma_tx_phy, GFP_KERNEL);
        if (!tx_ring->dma_tx)
                return -ENOMEM;
 
@@ -479,9 +479,9 @@ static int init_rx_ring(struct net_device *dev, u8 queue_no,
        rx_ring->queue_no = queue_no;
 
        /* allocate memory for RX descriptors */
-       rx_ring->dma_rx = dma_zalloc_coherent(priv->device,
-                                             rx_rsize * sizeof(struct sxgbe_rx_norm_desc),
-                                             &rx_ring->dma_rx_phy, GFP_KERNEL);
+       rx_ring->dma_rx = dma_alloc_coherent(priv->device,
+                                            rx_rsize * sizeof(struct sxgbe_rx_norm_desc),
+                                            &rx_ring->dma_rx_phy, GFP_KERNEL);
 
        if (rx_ring->dma_rx == NULL)
                return -ENOMEM;
index b6a5005..c080341 100644 (file)
@@ -6046,22 +6046,25 @@ static const struct efx_ef10_nvram_type_info efx_ef10_nvram_types[] = {
        { NVRAM_PARTITION_TYPE_EXPANSION_UEFI,     0,    0, "sfc_uefi" },
        { NVRAM_PARTITION_TYPE_STATUS,             0,    0, "sfc_status" }
 };
+#define EF10_NVRAM_PARTITION_COUNT     ARRAY_SIZE(efx_ef10_nvram_types)
 
 static int efx_ef10_mtd_probe_partition(struct efx_nic *efx,
                                        struct efx_mcdi_mtd_partition *part,
-                                       unsigned int type)
+                                       unsigned int type,
+                                       unsigned long *found)
 {
        MCDI_DECLARE_BUF(inbuf, MC_CMD_NVRAM_METADATA_IN_LEN);
        MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_METADATA_OUT_LENMAX);
        const struct efx_ef10_nvram_type_info *info;
        size_t size, erase_size, outlen;
+       int type_idx = 0;
        bool protected;
        int rc;
 
-       for (info = efx_ef10_nvram_types; ; info++) {
-               if (info ==
-                   efx_ef10_nvram_types + ARRAY_SIZE(efx_ef10_nvram_types))
+       for (type_idx = 0; ; type_idx++) {
+               if (type_idx == EF10_NVRAM_PARTITION_COUNT)
                        return -ENODEV;
+               info = efx_ef10_nvram_types + type_idx;
                if ((type & ~info->type_mask) == info->type)
                        break;
        }
@@ -6074,6 +6077,13 @@ static int efx_ef10_mtd_probe_partition(struct efx_nic *efx,
        if (protected)
                return -ENODEV; /* hide it */
 
+       /* If we've already exposed a partition of this type, hide this
+        * duplicate.  All operations on MTDs are keyed by the type anyway,
+        * so we can't act on the duplicate.
+        */
+       if (__test_and_set_bit(type_idx, found))
+               return -EEXIST;
+
        part->nvram_type = type;
 
        MCDI_SET_DWORD(inbuf, NVRAM_METADATA_IN_TYPE, type);
@@ -6105,6 +6115,7 @@ static int efx_ef10_mtd_probe_partition(struct efx_nic *efx,
 static int efx_ef10_mtd_probe(struct efx_nic *efx)
 {
        MCDI_DECLARE_BUF(outbuf, MC_CMD_NVRAM_PARTITIONS_OUT_LENMAX);
+       DECLARE_BITMAP(found, EF10_NVRAM_PARTITION_COUNT) = { 0 };
        struct efx_mcdi_mtd_partition *parts;
        size_t outlen, n_parts_total, i, n_parts;
        unsigned int type;
@@ -6133,11 +6144,13 @@ static int efx_ef10_mtd_probe(struct efx_nic *efx)
        for (i = 0; i < n_parts_total; i++) {
                type = MCDI_ARRAY_DWORD(outbuf, NVRAM_PARTITIONS_OUT_TYPE_ID,
                                        i);
-               rc = efx_ef10_mtd_probe_partition(efx, &parts[n_parts], type);
-               if (rc == 0)
-                       n_parts++;
-               else if (rc != -ENODEV)
+               rc = efx_ef10_mtd_probe_partition(efx, &parts[n_parts], type,
+                                                 found);
+               if (rc == -EEXIST || rc == -ENODEV)
+                       continue;
+               if (rc)
                        goto fail;
+               n_parts++;
        }
 
        rc = efx_mtd_add(efx, &parts[0].common, n_parts, sizeof(*parts));
index a8ecb33..9c07b51 100644 (file)
@@ -33,8 +33,8 @@
 int ef4_nic_alloc_buffer(struct ef4_nic *efx, struct ef4_buffer *buffer,
                         unsigned int len, gfp_t gfp_flags)
 {
-       buffer->addr = dma_zalloc_coherent(&efx->pci_dev->dev, len,
-                                          &buffer->dma_addr, gfp_flags);
+       buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len,
+                                         &buffer->dma_addr, gfp_flags);
        if (!buffer->addr)
                return -ENOMEM;
        buffer->len = len;
index aa1945a..c2d45a4 100644 (file)
@@ -34,8 +34,8 @@
 int efx_nic_alloc_buffer(struct efx_nic *efx, struct efx_buffer *buffer,
                         unsigned int len, gfp_t gfp_flags)
 {
-       buffer->addr = dma_zalloc_coherent(&efx->pci_dev->dev, len,
-                                          &buffer->dma_addr, gfp_flags);
+       buffer->addr = dma_alloc_coherent(&efx->pci_dev->dev, len,
+                                         &buffer->dma_addr, gfp_flags);
        if (!buffer->addr)
                return -ENOMEM;
        buffer->len = len;
index 703fbbe..0e1b7e9 100644 (file)
@@ -211,8 +211,8 @@ static void meth_check_link(struct net_device *dev)
 static int meth_init_tx_ring(struct meth_private *priv)
 {
        /* Init TX ring */
-       priv->tx_ring = dma_zalloc_coherent(NULL, TX_RING_BUFFER_SIZE,
-                                           &priv->tx_ring_dma, GFP_ATOMIC);
+       priv->tx_ring = dma_alloc_coherent(NULL, TX_RING_BUFFER_SIZE,
+                                          &priv->tx_ring_dma, GFP_ATOMIC);
        if (!priv->tx_ring)
                return -ENOMEM;
 
index 15c62c1..be47d86 100644 (file)
@@ -1037,7 +1037,7 @@ static void epic_tx(struct net_device *dev, struct epic_private *ep)
                skb = ep->tx_skbuff[entry];
                pci_unmap_single(ep->pci_dev, ep->tx_ring[entry].bufaddr,
                                 skb->len, PCI_DMA_TODEVICE);
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
                ep->tx_skbuff[entry] = NULL;
        }
 
index 05a0948..a181497 100644 (file)
@@ -1029,8 +1029,8 @@ static int netsec_alloc_dring(struct netsec_priv *priv, enum ring_id id)
        struct netsec_desc_ring *dring = &priv->desc_ring[id];
        int i;
 
-       dring->vaddr = dma_zalloc_coherent(priv->dev, DESC_SZ * DESC_NUM,
-                                          &dring->desc_dma, GFP_KERNEL);
+       dring->vaddr = dma_alloc_coherent(priv->dev, DESC_SZ * DESC_NUM,
+                                         &dring->desc_dma, GFP_KERNEL);
        if (!dring->vaddr)
                goto err;
 
index 7b92336..3b174ea 100644 (file)
@@ -1342,8 +1342,10 @@ static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
        }
 
        ret = phy_power_on(bsp_priv, true);
-       if (ret)
+       if (ret) {
+               gmac_clk_enable(bsp_priv, false);
                return ret;
+       }
 
        pm_runtime_enable(dev);
        pm_runtime_get_sync(dev);
index 20299f6..736e296 100644 (file)
@@ -241,15 +241,18 @@ static inline void dwmac4_get_timestamp(void *desc, u32 ats, u64 *ts)
 static int dwmac4_rx_check_timestamp(void *desc)
 {
        struct dma_desc *p = (struct dma_desc *)desc;
+       unsigned int rdes0 = le32_to_cpu(p->des0);
+       unsigned int rdes1 = le32_to_cpu(p->des1);
+       unsigned int rdes3 = le32_to_cpu(p->des3);
        u32 own, ctxt;
        int ret = 1;
 
-       own = p->des3 & RDES3_OWN;
-       ctxt = ((p->des3 & RDES3_CONTEXT_DESCRIPTOR)
+       own = rdes3 & RDES3_OWN;
+       ctxt = ((rdes3 & RDES3_CONTEXT_DESCRIPTOR)
                >> RDES3_CONTEXT_DESCRIPTOR_SHIFT);
 
        if (likely(!own && ctxt)) {
-               if ((p->des0 == 0xffffffff) && (p->des1 == 0xffffffff))
+               if ((rdes0 == 0xffffffff) && (rdes1 == 0xffffffff))
                        /* Corrupted value */
                        ret = -EINVAL;
                else
index 6c5092e..c5e2558 100644 (file)
@@ -263,6 +263,7 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
                                  struct stmmac_extra_stats *x, u32 chan)
 {
        u32 intr_status = readl(ioaddr + XGMAC_DMA_CH_STATUS(chan));
+       u32 intr_en = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));
        int ret = 0;
 
        /* ABNORMAL interrupts */
@@ -282,8 +283,7 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
                x->normal_irq_n++;
 
                if (likely(intr_status & XGMAC_RI)) {
-                       u32 value = readl(ioaddr + XGMAC_DMA_CH_INT_EN(chan));
-                       if (likely(value & XGMAC_RIE)) {
+                       if (likely(intr_en & XGMAC_RIE)) {
                                x->rx_normal_irq_n++;
                                ret |= handle_rx;
                        }
@@ -295,7 +295,7 @@ static int dwxgmac2_dma_interrupt(void __iomem *ioaddr,
        }
 
        /* Clear interrupts */
-       writel(~0x0, ioaddr + XGMAC_DMA_CH_STATUS(chan));
+       writel(intr_en & intr_status, ioaddr + XGMAC_DMA_CH_STATUS(chan));
 
        return ret;
 }
index d1f61c2..3c749c3 100644 (file)
@@ -696,33 +696,38 @@ static int stmmac_ethtool_op_set_eee(struct net_device *dev,
                                     struct ethtool_eee *edata)
 {
        struct stmmac_priv *priv = netdev_priv(dev);
+       int ret;
 
-       priv->eee_enabled = edata->eee_enabled;
-
-       if (!priv->eee_enabled)
+       if (!edata->eee_enabled) {
                stmmac_disable_eee_mode(priv);
-       else {
+       else {
                /* We are asking for enabling the EEE but it is safe
                 * to verify all by invoking the eee_init function.
                 * In case of failure it will return an error.
                 */
-               priv->eee_enabled = stmmac_eee_init(priv);
-               if (!priv->eee_enabled)
+               edata->eee_enabled = stmmac_eee_init(priv);
+               if (!edata->eee_enabled)
                        return -EOPNOTSUPP;
-
-               /* Do not change tx_lpi_timer in case of failure */
-               priv->tx_lpi_timer = edata->tx_lpi_timer;
        }
 
-       return phy_ethtool_set_eee(dev->phydev, edata);
+       ret = phy_ethtool_set_eee(dev->phydev, edata);
+       if (ret)
+               return ret;
+
+       priv->eee_enabled = edata->eee_enabled;
+       priv->tx_lpi_timer = edata->tx_lpi_timer;
+       return 0;
 }
 
 static u32 stmmac_usec2riwt(u32 usec, struct stmmac_priv *priv)
 {
        unsigned long clk = clk_get_rate(priv->plat->stmmac_clk);
 
-       if (!clk)
-               return 0;
+       if (!clk) {
+               clk = priv->plat->clk_ref_rate;
+               if (!clk)
+                       return 0;
+       }
 
        return (usec * (clk / 1000000)) / 256;
 }
@@ -731,8 +736,11 @@ static u32 stmmac_riwt2usec(u32 riwt, struct stmmac_priv *priv)
 {
        unsigned long clk = clk_get_rate(priv->plat->stmmac_clk);
 
-       if (!clk)
-               return 0;
+       if (!clk) {
+               clk = priv->plat->clk_ref_rate;
+               if (!clk)
+                       return 0;
+       }
 
        return (riwt * 256) / (clk / 1000000);
 }
index 0e0a078..685d204 100644 (file)
@@ -1549,22 +1549,18 @@ static int alloc_dma_rx_desc_resources(struct stmmac_priv *priv)
                        goto err_dma;
 
                if (priv->extend_desc) {
-                       rx_q->dma_erx = dma_zalloc_coherent(priv->device,
-                                                           DMA_RX_SIZE *
-                                                           sizeof(struct
-                                                           dma_extended_desc),
-                                                           &rx_q->dma_rx_phy,
-                                                           GFP_KERNEL);
+                       rx_q->dma_erx = dma_alloc_coherent(priv->device,
+                                                          DMA_RX_SIZE * sizeof(struct dma_extended_desc),
+                                                          &rx_q->dma_rx_phy,
+                                                          GFP_KERNEL);
                        if (!rx_q->dma_erx)
                                goto err_dma;
 
                } else {
-                       rx_q->dma_rx = dma_zalloc_coherent(priv->device,
-                                                          DMA_RX_SIZE *
-                                                          sizeof(struct
-                                                          dma_desc),
-                                                          &rx_q->dma_rx_phy,
-                                                          GFP_KERNEL);
+                       rx_q->dma_rx = dma_alloc_coherent(priv->device,
+                                                         DMA_RX_SIZE * sizeof(struct dma_desc),
+                                                         &rx_q->dma_rx_phy,
+                                                         GFP_KERNEL);
                        if (!rx_q->dma_rx)
                                goto err_dma;
                }
@@ -1612,21 +1608,17 @@ static int alloc_dma_tx_desc_resources(struct stmmac_priv *priv)
                        goto err_dma;
 
                if (priv->extend_desc) {
-                       tx_q->dma_etx = dma_zalloc_coherent(priv->device,
-                                                           DMA_TX_SIZE *
-                                                           sizeof(struct
-                                                           dma_extended_desc),
-                                                           &tx_q->dma_tx_phy,
-                                                           GFP_KERNEL);
+                       tx_q->dma_etx = dma_alloc_coherent(priv->device,
+                                                          DMA_TX_SIZE * sizeof(struct dma_extended_desc),
+                                                          &tx_q->dma_tx_phy,
+                                                          GFP_KERNEL);
                        if (!tx_q->dma_etx)
                                goto err_dma;
                } else {
-                       tx_q->dma_tx = dma_zalloc_coherent(priv->device,
-                                                          DMA_TX_SIZE *
-                                                          sizeof(struct
-                                                                 dma_desc),
-                                                          &tx_q->dma_tx_phy,
-                                                          GFP_KERNEL);
+                       tx_q->dma_tx = dma_alloc_coherent(priv->device,
+                                                         DMA_TX_SIZE * sizeof(struct dma_desc),
+                                                         &tx_q->dma_tx_phy,
+                                                         GFP_KERNEL);
                        if (!tx_q->dma_tx)
                                goto err_dma;
                }
@@ -3031,10 +3023,22 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
 
        tx_q = &priv->tx_queue[queue];
 
+       if (priv->tx_path_in_lpi_mode)
+               stmmac_disable_eee_mode(priv);
+
        /* Manage oversized TCP frames for GMAC4 device */
        if (skb_is_gso(skb) && priv->tso) {
-               if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6))
+               if (skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6)) {
+                       /*
+                        * There is no way to determine the number of TSO
+                        * capable Queues. Let's use always the Queue 0
+                        * because if TSO is supported then at least this
+                        * one will be capable.
+                        */
+                       skb_set_queue_mapping(skb, 0);
+
                        return stmmac_tso_xmit(skb, dev);
+               }
        }
 
        if (unlikely(stmmac_tx_avail(priv, queue) < nfrags + 1)) {
@@ -3049,9 +3053,6 @@ static netdev_tx_t stmmac_xmit(struct sk_buff *skb, struct net_device *dev)
                return NETDEV_TX_BUSY;
        }
 
-       if (priv->tx_path_in_lpi_mode)
-               stmmac_disable_eee_mode(priv);
-
        entry = tx_q->cur_tx;
        first_entry = entry;
        WARN_ON(tx_q->tx_skbuff[first_entry]);
@@ -3525,27 +3526,28 @@ static int stmmac_napi_poll(struct napi_struct *napi, int budget)
        struct stmmac_channel *ch =
                container_of(napi, struct stmmac_channel, napi);
        struct stmmac_priv *priv = ch->priv_data;
-       int work_done = 0, work_rem = budget;
+       int work_done, rx_done = 0, tx_done = 0;
        u32 chan = ch->index;
 
        priv->xstats.napi_poll++;
 
-       if (ch->has_tx) {
-               int done = stmmac_tx_clean(priv, work_rem, chan);
+       if (ch->has_tx)
+               tx_done = stmmac_tx_clean(priv, budget, chan);
+       if (ch->has_rx)
+               rx_done = stmmac_rx(priv, budget, chan);
 
-               work_done += done;
-               work_rem -= done;
-       }
+       work_done = max(rx_done, tx_done);
+       work_done = min(work_done, budget);
 
-       if (ch->has_rx) {
-               int done = stmmac_rx(priv, work_rem, chan);
+       if (work_done < budget && napi_complete_done(napi, work_done)) {
+               int stat;
 
-               work_done += done;
-               work_rem -= done;
-       }
-
-       if (work_done < budget && napi_complete_done(napi, work_done))
                stmmac_enable_dma_irq(priv, priv->ioaddr, chan);
+               stat = stmmac_dma_interrupt_status(priv, priv->ioaddr,
+                                                  &priv->xstats, chan);
+               if (stat && napi_reschedule(napi))
+                       stmmac_disable_dma_irq(priv, priv->ioaddr, chan);
+       }
 
        return work_done;
 }
@@ -4168,6 +4170,18 @@ static int stmmac_hw_init(struct stmmac_priv *priv)
                        return ret;
        }
 
+       /* Rx Watchdog is available in the COREs newer than the 3.40.
+        * In some case, for example on bugged HW this feature
+        * has to be disable and this can be done by passing the
+        * riwt_off field from the platform.
+        */
+       if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
+           (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
+               priv->use_riwt = 1;
+               dev_info(priv->device,
+                        "Enable RX Mitigation via HW Watchdog Timer\n");
+       }
+
        return 0;
 }
 
@@ -4300,18 +4314,6 @@ int stmmac_dvr_probe(struct device *device,
        if (flow_ctrl)
                priv->flow_ctrl = FLOW_AUTO;    /* RX/TX pause on */
 
-       /* Rx Watchdog is available in the COREs newer than the 3.40.
-        * In some case, for example on bugged HW this feature
-        * has to be disable and this can be done by passing the
-        * riwt_off field from the platform.
-        */
-       if (((priv->synopsys_id >= DWMAC_CORE_3_50) ||
-           (priv->plat->has_xgmac)) && (!priv->plat->riwt_off)) {
-               priv->use_riwt = 1;
-               dev_info(priv->device,
-                        "Enable RX Mitigation via HW Watchdog Timer\n");
-       }
-
        /* Setup channels NAPI */
        maxq = max(priv->plat->rx_queues_to_use, priv->plat->tx_queues_to_use);
 
index c54a50d..d819e8e 100644 (file)
@@ -299,7 +299,17 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
  */
 static void stmmac_pci_remove(struct pci_dev *pdev)
 {
+       int i;
+
        stmmac_dvr_remove(&pdev->dev);
+
+       for (i = 0; i <= PCI_STD_RESOURCE_END; i++) {
+               if (pci_resource_len(pdev, i) == 0)
+                       continue;
+               pcim_iounmap_regions(pdev, BIT(i));
+               break;
+       }
+
        pci_disable_device(pdev);
 }
 
index 531294f..58ea18a 100644 (file)
@@ -301,6 +301,8 @@ static int tc_setup_cbs(struct stmmac_priv *priv,
        /* Queue 0 is not AVB capable */
        if (queue <= 0 || queue >= tx_queues_count)
                return -EINVAL;
+       if (!priv->dma_cap.av)
+               return -EOPNOTSUPP;
        if (priv->speed != SPEED_100 && priv->speed != SPEED_1000)
                return -EOPNOTSUPP;
 
index 9020b08..6fc05c1 100644 (file)
@@ -1,22 +1,9 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
 /* cassini.c: Sun Microsystems Cassini(+) ethernet driver.
  *
  * Copyright (C) 2004 Sun Microsystems Inc.
  * Copyright (C) 2003 Adrian Sun (asun@darksunrising.com)
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- *
  * This driver uses the sungem driver (c) David Miller
  * (davem@redhat.com) as its basis.
  *
@@ -1911,7 +1898,7 @@ static inline void cas_tx_ringN(struct cas *cp, int ring, int limit)
                cp->net_stats[ring].tx_packets++;
                cp->net_stats[ring].tx_bytes += skb->len;
                spin_unlock(&cp->stat_lock[ring]);
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
        }
        cp->tx_old[ring] = entry;
 
index 13f3860..ae5f05f 100644 (file)
@@ -1,23 +1,10 @@
-/* SPDX-License-Identifier: GPL-2.0 */
+/* SPDX-License-Identifier: GPL-2.0+ */
 /* $Id: cassini.h,v 1.16 2004/08/17 21:15:16 zaumen Exp $
  * cassini.h: Definitions for Sun Microsystems Cassini(+) ethernet driver.
  *
  * Copyright (C) 2004 Sun Microsystems Inc.
  * Copyright (c) 2003 Adrian Sun (asun@darksunrising.com)
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License as
- * published by the Free Software Foundation; either version 2 of the
- * License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
- *
  * vendor id: 0x108E (Sun Microsystems, Inc.)
  * device id: 0xabba (Cassini)
  * revision ids: 0x01 = Cassini
index 720b7ac..e9b757b 100644 (file)
@@ -781,7 +781,7 @@ static void bigmac_tx(struct bigmac *bp)
 
                DTX(("skb(%p) ", skb));
                bp->tx_skbs[elem] = NULL;
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
 
                elem = NEXT_TX(elem);
        }
index ff641cf..d007dfe 100644 (file)
@@ -1962,7 +1962,7 @@ static void happy_meal_tx(struct happy_meal *hp)
                        this = &txbase[elem];
                }
 
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
                dev->stats.tx_packets++;
        }
        hp->tx_old = elem;
index dc966dd..b24c111 100644 (file)
@@ -1739,7 +1739,7 @@ static void bdx_tx_cleanup(struct bdx_priv *priv)
                tx_level -= db->rptr->len;      /* '-' koz len is negative */
 
                /* now should come skb pointer - free it */
-               dev_kfree_skb_irq(db->rptr->addr.skb);
+               dev_consume_skb_irq(db->rptr->addr.skb);
                bdx_tx_db_inc_rptr(db);
        }
 
index 810dfc7..e2d47b2 100644 (file)
@@ -608,7 +608,7 @@ static void cpmac_end_xmit(struct net_device *dev, int queue)
                        netdev_dbg(dev, "sent 0x%p, len=%d\n",
                                   desc->skb, desc->skb->len);
 
-               dev_kfree_skb_irq(desc->skb);
+               dev_consume_skb_irq(desc->skb);
                desc->skb = NULL;
                if (__netif_subqueue_stopped(dev, queue))
                        netif_wake_subqueue(dev, queue);
index 1f61226..d847f67 100644 (file)
@@ -259,7 +259,7 @@ static int netcp_module_probe(struct netcp_device *netcp_device,
                const char *name;
                char node_name[32];
 
-               if (of_property_read_string(node, "label", &name) < 0) {
+               if (of_property_read_string(child, "label", &name) < 0) {
                        snprintf(node_name, sizeof(node_name), "%pOFn", child);
                        name = node_name;
                }
index edcd1e6..37925a1 100644 (file)
@@ -1311,13 +1311,13 @@ static int tsi108_open(struct net_device *dev)
                       data->id, dev->irq, dev->name);
        }
 
-       data->rxring = dma_zalloc_coherent(&data->pdev->dev, rxring_size,
-                       &data->rxdma, GFP_KERNEL);
+       data->rxring = dma_alloc_coherent(&data->pdev->dev, rxring_size,
+                                         &data->rxdma, GFP_KERNEL);
        if (!data->rxring)
                return -ENOMEM;
 
-       data->txring = dma_zalloc_coherent(&data->pdev->dev, txring_size,
-                       &data->txdma, GFP_KERNEL);
+       data->txring = dma_alloc_coherent(&data->pdev->dev, txring_size,
+                                         &data->txdma, GFP_KERNEL);
        if (!data->txring) {
                dma_free_coherent(&data->pdev->dev, rxring_size, data->rxring,
                                    data->rxdma);
index 8241269..27f6cf1 100644 (file)
@@ -1740,7 +1740,7 @@ static void velocity_free_tx_buf(struct velocity_info *vptr,
                dma_unmap_single(vptr->dev, tdinfo->skb_dma[i],
                                 le16_to_cpu(pktlen), DMA_TO_DEVICE);
        }
-       dev_kfree_skb_irq(skb);
+       dev_consume_skb_irq(skb);
        tdinfo->skb = NULL;
 }
 
index 2241f98..15bb058 100644 (file)
@@ -243,15 +243,15 @@ static int temac_dma_bd_init(struct net_device *ndev)
 
        /* allocate the tx and rx ring buffer descriptors. */
        /* returns a virtual address and a physical address. */
-       lp->tx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
-                                         sizeof(*lp->tx_bd_v) * TX_BD_NUM,
-                                         &lp->tx_bd_p, GFP_KERNEL);
+       lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+                                        sizeof(*lp->tx_bd_v) * TX_BD_NUM,
+                                        &lp->tx_bd_p, GFP_KERNEL);
        if (!lp->tx_bd_v)
                goto out;
 
-       lp->rx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
-                                         sizeof(*lp->rx_bd_v) * RX_BD_NUM,
-                                         &lp->rx_bd_p, GFP_KERNEL);
+       lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+                                        sizeof(*lp->rx_bd_v) * RX_BD_NUM,
+                                        &lp->rx_bd_p, GFP_KERNEL);
        if (!lp->rx_bd_v)
                goto out;
 
index 12a1460..0789d8a 100644 (file)
@@ -199,15 +199,15 @@ static int axienet_dma_bd_init(struct net_device *ndev)
        lp->rx_bd_ci = 0;
 
        /* Allocate the Tx and Rx buffer descriptors. */
-       lp->tx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
-                                         sizeof(*lp->tx_bd_v) * TX_BD_NUM,
-                                         &lp->tx_bd_p, GFP_KERNEL);
+       lp->tx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+                                        sizeof(*lp->tx_bd_v) * TX_BD_NUM,
+                                        &lp->tx_bd_p, GFP_KERNEL);
        if (!lp->tx_bd_v)
                goto out;
 
-       lp->rx_bd_v = dma_zalloc_coherent(ndev->dev.parent,
-                                         sizeof(*lp->rx_bd_v) * RX_BD_NUM,
-                                         &lp->rx_bd_p, GFP_KERNEL);
+       lp->rx_bd_v = dma_alloc_coherent(ndev->dev.parent,
+                                        sizeof(*lp->rx_bd_v) * RX_BD_NUM,
+                                        &lp->rx_bd_p, GFP_KERNEL);
        if (!lp->rx_bd_v)
                goto out;
 
index 61fceee..56b7791 100644 (file)
@@ -1139,9 +1139,9 @@ static int dfx_driver_init(struct net_device *dev, const char *print_name,
 #endif
                                        sizeof(PI_CONSUMER_BLOCK) +
                                        (PI_ALIGN_K_DESC_BLK - 1);
-       bp->kmalloced = top_v = dma_zalloc_coherent(bp->bus_dev, alloc_size,
-                                                   &bp->kmalloced_dma,
-                                                   GFP_ATOMIC);
+       bp->kmalloced = top_v = dma_alloc_coherent(bp->bus_dev, alloc_size,
+                                                  &bp->kmalloced_dma,
+                                                  GFP_ATOMIC);
        if (top_v == NULL)
                return DFX_K_FAILURE;
 
@@ -3512,7 +3512,7 @@ static int dfx_xmt_done(DFX_board_t *bp)
                                 bp->descr_block_virt->xmt_data[comp].long_1,
                                 p_xmt_drv_descr->p_skb->len,
                                 DMA_TO_DEVICE);
-               dev_kfree_skb_irq(p_xmt_drv_descr->p_skb);
+               dev_consume_skb_irq(p_xmt_drv_descr->p_skb);
 
                /*
                 * Move to start of next packet by updating completion index
index 72433f3..5d661f6 100644 (file)
@@ -409,10 +409,10 @@ static  int skfp_driver_init(struct net_device *dev)
        if (bp->SharedMemSize > 0) {
                bp->SharedMemSize += 16;        // for descriptor alignment
 
-               bp->SharedMemAddr = dma_zalloc_coherent(&bp->pdev.dev,
-                                                       bp->SharedMemSize,
-                                                       &bp->SharedMemDMA,
-                                                       GFP_ATOMIC);
+               bp->SharedMemAddr = dma_alloc_coherent(&bp->pdev.dev,
+                                                      bp->SharedMemSize,
+                                                      &bp->SharedMemDMA,
+                                                      GFP_ATOMIC);
                if (!bp->SharedMemAddr) {
                        printk("could not allocate mem for ");
                        printk("hardware module: %ld byte\n",
index 58bbba8..3377ac6 100644 (file)
@@ -1512,9 +1512,13 @@ static void geneve_link_config(struct net_device *dev,
        }
 #if IS_ENABLED(CONFIG_IPV6)
        case AF_INET6: {
-               struct rt6_info *rt = rt6_lookup(geneve->net,
-                                                &info->key.u.ipv6.dst, NULL, 0,
-                                                NULL, 0);
+               struct rt6_info *rt;
+
+               if (!__in6_dev_get(dev))
+                       break;
+
+               rt = rt6_lookup(geneve->net, &info->key.u.ipv6.dst, NULL, 0,
+                               NULL, 0);
 
                if (rt && rt->dst.dev)
                        ldev_mtu = rt->dst.dev->mtu - GENEVE_IPV6_HLEN;
index ef6f766..e859ae2 100644 (file)
@@ -144,6 +144,8 @@ struct hv_netvsc_packet {
        u32 total_data_buflen;
 };
 
+#define NETVSC_HASH_KEYLEN 40
+
 struct netvsc_device_info {
        unsigned char mac_adr[ETH_ALEN];
        u32  num_chn;
@@ -151,6 +153,8 @@ struct netvsc_device_info {
        u32  recv_sections;
        u32  send_section_size;
        u32  recv_section_size;
+
+       u8 rss_key[NETVSC_HASH_KEYLEN];
 };
 
 enum rndis_device_state {
@@ -160,8 +164,6 @@ enum rndis_device_state {
        RNDIS_DEV_DATAINITIALIZED,
 };
 
-#define NETVSC_HASH_KEYLEN 40
-
 struct rndis_device {
        struct net_device *ndev;
 
@@ -209,7 +211,9 @@ int netvsc_recv_callback(struct net_device *net,
 void netvsc_channel_cb(void *context);
 int netvsc_poll(struct napi_struct *napi, int budget);
 
-int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev);
+int rndis_set_subchannel(struct net_device *ndev,
+                        struct netvsc_device *nvdev,
+                        struct netvsc_device_info *dev_info);
 int rndis_filter_open(struct netvsc_device *nvdev);
 int rndis_filter_close(struct netvsc_device *nvdev);
 struct netvsc_device *rndis_filter_device_add(struct hv_device *dev,
@@ -1177,7 +1181,7 @@ enum ndis_per_pkt_info_type {
 
 enum rndis_per_pkt_info_interal_type {
        RNDIS_PKTINFO_ID = 1,
-       /* Add more memebers here */
+       /* Add more members here */
 
        RNDIS_PKTINFO_MAX
 };
index 922054c..813d195 100644 (file)
@@ -84,7 +84,7 @@ static void netvsc_subchan_work(struct work_struct *w)
 
        rdev = nvdev->extension;
        if (rdev) {
-               ret = rndis_set_subchannel(rdev->ndev, nvdev);
+               ret = rndis_set_subchannel(rdev->ndev, nvdev, NULL);
                if (ret == 0) {
                        netif_device_attach(rdev->ndev);
                } else {
@@ -1331,7 +1331,7 @@ void netvsc_channel_cb(void *context)
        prefetch(hv_get_ring_buffer(rbi) + rbi->priv_read_index);
 
        if (napi_schedule_prep(&nvchan->napi)) {
-               /* disable interupts from host */
+               /* disable interrupts from host */
                hv_begin_read(rbi);
 
                __napi_schedule_irqoff(&nvchan->napi);
index 91ed15e..256adbd 100644 (file)
@@ -370,7 +370,7 @@ static u32 fill_pg_buf(struct page *page, u32 offset, u32 len,
 {
        int j = 0;
 
-       /* Deal with compund pages by ignoring unused part
+       /* Deal with compound pages by ignoring unused part
         * of the page.
         */
        page += (offset >> PAGE_SHIFT);
@@ -858,6 +858,39 @@ static void netvsc_get_channels(struct net_device *net,
        }
 }
 
+/* Alloc struct netvsc_device_info, and initialize it from either existing
+ * struct netvsc_device, or from default values.
+ */
+static struct netvsc_device_info *netvsc_devinfo_get
+                       (struct netvsc_device *nvdev)
+{
+       struct netvsc_device_info *dev_info;
+
+       dev_info = kzalloc(sizeof(*dev_info), GFP_ATOMIC);
+
+       if (!dev_info)
+               return NULL;
+
+       if (nvdev) {
+               dev_info->num_chn = nvdev->num_chn;
+               dev_info->send_sections = nvdev->send_section_cnt;
+               dev_info->send_section_size = nvdev->send_section_size;
+               dev_info->recv_sections = nvdev->recv_section_cnt;
+               dev_info->recv_section_size = nvdev->recv_section_size;
+
+               memcpy(dev_info->rss_key, nvdev->extension->rss_key,
+                      NETVSC_HASH_KEYLEN);
+       } else {
+               dev_info->num_chn = VRSS_CHANNEL_DEFAULT;
+               dev_info->send_sections = NETVSC_DEFAULT_TX;
+               dev_info->send_section_size = NETVSC_SEND_SECTION_SIZE;
+               dev_info->recv_sections = NETVSC_DEFAULT_RX;
+               dev_info->recv_section_size = NETVSC_RECV_SECTION_SIZE;
+       }
+
+       return dev_info;
+}
+
 static int netvsc_detach(struct net_device *ndev,
                         struct netvsc_device *nvdev)
 {
@@ -909,7 +942,7 @@ static int netvsc_attach(struct net_device *ndev,
                return PTR_ERR(nvdev);
 
        if (nvdev->num_chn > 1) {
-               ret = rndis_set_subchannel(ndev, nvdev);
+               ret = rndis_set_subchannel(ndev, nvdev, dev_info);
 
                /* if unavailable, just proceed with one queue */
                if (ret) {
@@ -943,7 +976,7 @@ static int netvsc_set_channels(struct net_device *net,
        struct net_device_context *net_device_ctx = netdev_priv(net);
        struct netvsc_device *nvdev = rtnl_dereference(net_device_ctx->nvdev);
        unsigned int orig, count = channels->combined_count;
-       struct netvsc_device_info device_info;
+       struct netvsc_device_info *device_info;
        int ret;
 
        /* We do not support separate count for rx, tx, or other */
@@ -962,24 +995,26 @@ static int netvsc_set_channels(struct net_device *net,
 
        orig = nvdev->num_chn;
 
-       memset(&device_info, 0, sizeof(device_info));
-       device_info.num_chn = count;
-       device_info.send_sections = nvdev->send_section_cnt;
-       device_info.send_section_size = nvdev->send_section_size;
-       device_info.recv_sections = nvdev->recv_section_cnt;
-       device_info.recv_section_size = nvdev->recv_section_size;
+       device_info = netvsc_devinfo_get(nvdev);
+
+       if (!device_info)
+               return -ENOMEM;
+
+       device_info->num_chn = count;
 
        ret = netvsc_detach(net, nvdev);
        if (ret)
-               return ret;
+               goto out;
 
-       ret = netvsc_attach(net, &device_info);
+       ret = netvsc_attach(net, device_info);
        if (ret) {
-               device_info.num_chn = orig;
-               if (netvsc_attach(net, &device_info))
+               device_info->num_chn = orig;
+               if (netvsc_attach(net, device_info))
                        netdev_err(net, "restoring channel setting failed\n");
        }
 
+out:
+       kfree(device_info);
        return ret;
 }
 
@@ -1048,48 +1083,45 @@ static int netvsc_change_mtu(struct net_device *ndev, int mtu)
        struct net_device *vf_netdev = rtnl_dereference(ndevctx->vf_netdev);
        struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
        int orig_mtu = ndev->mtu;
-       struct netvsc_device_info device_info;
+       struct netvsc_device_info *device_info;
        int ret = 0;
 
        if (!nvdev || nvdev->destroy)
                return -ENODEV;
 
+       device_info = netvsc_devinfo_get(nvdev);
+
+       if (!device_info)
+               return -ENOMEM;
+
        /* Change MTU of underlying VF netdev first. */
        if (vf_netdev) {
                ret = dev_set_mtu(vf_netdev, mtu);
                if (ret)
-                       return ret;
+                       goto out;
        }
 
-       memset(&device_info, 0, sizeof(device_info));
-       device_info.num_chn = nvdev->num_chn;
-       device_info.send_sections = nvdev->send_section_cnt;
-       device_info.send_section_size = nvdev->send_section_size;
-       device_info.recv_sections = nvdev->recv_section_cnt;
-       device_info.recv_section_size = nvdev->recv_section_size;
-
        ret = netvsc_detach(ndev, nvdev);
        if (ret)
                goto rollback_vf;
 
        ndev->mtu = mtu;
 
-       ret = netvsc_attach(ndev, &device_info);
-       if (ret)
-               goto rollback;
-
-       return 0;
+       ret = netvsc_attach(ndev, device_info);
+       if (!ret)
+               goto out;
 
-rollback:
        /* Attempt rollback to original MTU */
        ndev->mtu = orig_mtu;
 
-       if (netvsc_attach(ndev, &device_info))
+       if (netvsc_attach(ndev, device_info))
                netdev_err(ndev, "restoring mtu failed\n");
 rollback_vf:
        if (vf_netdev)
                dev_set_mtu(vf_netdev, orig_mtu);
 
+out:
+       kfree(device_info);
        return ret;
 }
 
@@ -1674,7 +1706,7 @@ static int netvsc_set_ringparam(struct net_device *ndev,
 {
        struct net_device_context *ndevctx = netdev_priv(ndev);
        struct netvsc_device *nvdev = rtnl_dereference(ndevctx->nvdev);
-       struct netvsc_device_info device_info;
+       struct netvsc_device_info *device_info;
        struct ethtool_ringparam orig;
        u32 new_tx, new_rx;
        int ret = 0;
@@ -1694,26 +1726,29 @@ static int netvsc_set_ringparam(struct net_device *ndev,
            new_rx == orig.rx_pending)
                return 0;        /* no change */
 
-       memset(&device_info, 0, sizeof(device_info));
-       device_info.num_chn = nvdev->num_chn;
-       device_info.send_sections = new_tx;
-       device_info.send_section_size = nvdev->send_section_size;
-       device_info.recv_sections = new_rx;
-       device_info.recv_section_size = nvdev->recv_section_size;
+       device_info = netvsc_devinfo_get(nvdev);
+
+       if (!device_info)
+               return -ENOMEM;
+
+       device_info->send_sections = new_tx;
+       device_info->recv_sections = new_rx;
 
        ret = netvsc_detach(ndev, nvdev);
        if (ret)
-               return ret;
+               goto out;
 
-       ret = netvsc_attach(ndev, &device_info);
+       ret = netvsc_attach(ndev, device_info);
        if (ret) {
-               device_info.send_sections = orig.tx_pending;
-               device_info.recv_sections = orig.rx_pending;
+               device_info->send_sections = orig.tx_pending;
+               device_info->recv_sections = orig.rx_pending;
 
-               if (netvsc_attach(ndev, &device_info))
+               if (netvsc_attach(ndev, device_info))
                        netdev_err(ndev, "restoring ringparam failed");
        }
 
+out:
+       kfree(device_info);
        return ret;
 }
 
@@ -2088,7 +2123,7 @@ static int netvsc_register_vf(struct net_device *vf_netdev)
        if (!netvsc_dev || rtnl_dereference(net_device_ctx->vf_netdev))
                return NOTIFY_DONE;
 
-       /* if syntihetic interface is a different namespace,
+       /* if synthetic interface is a different namespace,
         * then move the VF to that namespace; join will be
         * done again in that context.
         */
@@ -2167,7 +2202,7 @@ static int netvsc_probe(struct hv_device *dev,
 {
        struct net_device *net = NULL;
        struct net_device_context *net_device_ctx;
-       struct netvsc_device_info device_info;
+       struct netvsc_device_info *device_info = NULL;
        struct netvsc_device *nvdev;
        int ret = -ENOMEM;
 
@@ -2214,21 +2249,21 @@ static int netvsc_probe(struct hv_device *dev,
        netif_set_real_num_rx_queues(net, 1);
 
        /* Notify the netvsc driver of the new device */
-       memset(&device_info, 0, sizeof(device_info));
-       device_info.num_chn = VRSS_CHANNEL_DEFAULT;
-       device_info.send_sections = NETVSC_DEFAULT_TX;
-       device_info.send_section_size = NETVSC_SEND_SECTION_SIZE;
-       device_info.recv_sections = NETVSC_DEFAULT_RX;
-       device_info.recv_section_size = NETVSC_RECV_SECTION_SIZE;
-
-       nvdev = rndis_filter_device_add(dev, &device_info);
+       device_info = netvsc_devinfo_get(NULL);
+
+       if (!device_info) {
+               ret = -ENOMEM;
+               goto devinfo_failed;
+       }
+
+       nvdev = rndis_filter_device_add(dev, device_info);
        if (IS_ERR(nvdev)) {
                ret = PTR_ERR(nvdev);
                netdev_err(net, "unable to add netvsc device (ret %d)\n", ret);
                goto rndis_failed;
        }
 
-       memcpy(net->dev_addr, device_info.mac_adr, ETH_ALEN);
+       memcpy(net->dev_addr, device_info->mac_adr, ETH_ALEN);
 
        /* We must get rtnl lock before scheduling nvdev->subchan_work,
         * otherwise netvsc_subchan_work() can get rtnl lock first and wait
@@ -2236,7 +2271,7 @@ static int netvsc_probe(struct hv_device *dev,
         * netvsc_probe() can't get rtnl lock and as a result vmbus_onoffer()
         * -> ... -> device_add() -> ... -> __device_attach() can't get
         * the device lock, so all the subchannels can't be processed --
-        * finally netvsc_subchan_work() hangs for ever.
+        * finally netvsc_subchan_work() hangs forever.
         */
        rtnl_lock();
 
@@ -2266,12 +2301,16 @@ static int netvsc_probe(struct hv_device *dev,
 
        list_add(&net_device_ctx->list, &netvsc_dev_list);
        rtnl_unlock();
+
+       kfree(device_info);
        return 0;
 
 register_failed:
        rtnl_unlock();
        rndis_filter_device_remove(dev, nvdev);
 rndis_failed:
+       kfree(device_info);
+devinfo_failed:
        free_percpu(net_device_ctx->vf_stats);
 no_stats:
        hv_set_drvdata(dev, NULL);
index 8b537a0..73b6059 100644 (file)
@@ -774,8 +774,8 @@ cleanup:
        return ret;
 }
 
-int rndis_filter_set_rss_param(struct rndis_device *rdev,
-                              const u8 *rss_key)
+static int rndis_set_rss_param_msg(struct rndis_device *rdev,
+                                  const u8 *rss_key, u16 flag)
 {
        struct net_device *ndev = rdev->ndev;
        struct rndis_request *request;
@@ -804,7 +804,7 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
        rssp->hdr.type = NDIS_OBJECT_TYPE_RSS_PARAMETERS;
        rssp->hdr.rev = NDIS_RECEIVE_SCALE_PARAMETERS_REVISION_2;
        rssp->hdr.size = sizeof(struct ndis_recv_scale_param);
-       rssp->flag = 0;
+       rssp->flag = flag;
        rssp->hashinfo = NDIS_HASH_FUNC_TOEPLITZ | NDIS_HASH_IPV4 |
                         NDIS_HASH_TCP_IPV4 | NDIS_HASH_IPV6 |
                         NDIS_HASH_TCP_IPV6;
@@ -829,9 +829,12 @@ int rndis_filter_set_rss_param(struct rndis_device *rdev,
 
        wait_for_completion(&request->wait_event);
        set_complete = &request->response_msg.msg.set_complete;
-       if (set_complete->status == RNDIS_STATUS_SUCCESS)
-               memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN);
-       else {
+       if (set_complete->status == RNDIS_STATUS_SUCCESS) {
+               if (!(flag & NDIS_RSS_PARAM_FLAG_DISABLE_RSS) &&
+                   !(flag & NDIS_RSS_PARAM_FLAG_HASH_KEY_UNCHANGED))
+                       memcpy(rdev->rss_key, rss_key, NETVSC_HASH_KEYLEN);
+
+       } else {
                netdev_err(ndev, "Fail to set RSS parameters:0x%x\n",
                           set_complete->status);
                ret = -EINVAL;
@@ -842,6 +845,16 @@ cleanup:
        return ret;
 }
 
+int rndis_filter_set_rss_param(struct rndis_device *rdev,
+                              const u8 *rss_key)
+{
+       /* Disable RSS before change */
+       rndis_set_rss_param_msg(rdev, rss_key,
+                               NDIS_RSS_PARAM_FLAG_DISABLE_RSS);
+
+       return rndis_set_rss_param_msg(rdev, rss_key, 0);
+}
+
 static int rndis_filter_query_device_link_status(struct rndis_device *dev,
                                                 struct netvsc_device *net_device)
 {
@@ -1121,7 +1134,9 @@ static void netvsc_sc_open(struct vmbus_channel *new_sc)
  * This breaks overlap of processing the host message for the
  * new primary channel with the initialization of sub-channels.
  */
-int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev)
+int rndis_set_subchannel(struct net_device *ndev,
+                        struct netvsc_device *nvdev,
+                        struct netvsc_device_info *dev_info)
 {
        struct nvsp_message *init_packet = &nvdev->channel_init_pkt;
        struct net_device_context *ndev_ctx = netdev_priv(ndev);
@@ -1161,8 +1176,11 @@ int rndis_set_subchannel(struct net_device *ndev, struct netvsc_device *nvdev)
        wait_event(nvdev->subchan_open,
                   atomic_read(&nvdev->open_chn) == nvdev->num_chn);
 
-       /* ignore failues from setting rss parameters, still have channels */
-       rndis_filter_set_rss_param(rdev, netvsc_hash_key);
+       /* ignore failures from setting rss parameters, still have channels */
+       if (dev_info)
+               rndis_filter_set_rss_param(rdev, dev_info->rss_key);
+       else
+               rndis_filter_set_rss_param(rdev, netvsc_hash_key);
 
        netif_set_real_num_tx_queues(ndev, nvdev->num_chn);
        netif_set_real_num_rx_queues(ndev, nvdev->num_chn);
index 44de81e..c589f5a 100644 (file)
@@ -905,9 +905,9 @@ mcr20a_irq_clean_complete(void *context)
                }
                break;
        case (DAR_IRQSTS1_RXIRQ | DAR_IRQSTS1_SEQIRQ):
-                       /* rx is starting */
-                       dev_dbg(printdev(lp), "RX is starting\n");
-                       mcr20a_handle_rx(lp);
+               /* rx is starting */
+               dev_dbg(printdev(lp), "RX is starting\n");
+               mcr20a_handle_rx(lp);
                break;
        case (DAR_IRQSTS1_RXIRQ | DAR_IRQSTS1_TXIRQ | DAR_IRQSTS1_SEQIRQ):
                if (lp->is_tx) {
index 19bdde6..07e41c4 100644 (file)
@@ -100,12 +100,12 @@ static int ipvlan_set_port_mode(struct ipvl_port *port, u16 nval,
                        err = ipvlan_register_nf_hook(read_pnet(&port->pnet));
                        if (!err) {
                                mdev->l3mdev_ops = &ipvl_l3mdev_ops;
-                               mdev->priv_flags |= IFF_L3MDEV_MASTER;
+                               mdev->priv_flags |= IFF_L3MDEV_RX_HANDLER;
                        } else
                                goto fail;
                } else if (port->mode == IPVLAN_MODE_L3S) {
                        /* Old mode was L3S */
-                       mdev->priv_flags &= ~IFF_L3MDEV_MASTER;
+                       mdev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
                        ipvlan_unregister_nf_hook(read_pnet(&port->pnet));
                        mdev->l3mdev_ops = NULL;
                }
@@ -167,7 +167,7 @@ static void ipvlan_port_destroy(struct net_device *dev)
        struct sk_buff *skb;
 
        if (port->mode == IPVLAN_MODE_L3S) {
-               dev->priv_flags &= ~IFF_L3MDEV_MASTER;
+               dev->priv_flags &= ~IFF_L3MDEV_RX_HANDLER;
                ipvlan_unregister_nf_hook(dev_net(dev));
                dev->l3mdev_ops = NULL;
        }
@@ -499,6 +499,8 @@ static int ipvlan_nl_changelink(struct net_device *dev,
 
        if (!data)
                return 0;
+       if (!ns_capable(dev_net(ipvlan->phy_dev)->user_ns, CAP_NET_ADMIN))
+               return -EPERM;
 
        if (data[IFLA_IPVLAN_MODE]) {
                u16 nmode = nla_get_u16(data[IFLA_IPVLAN_MODE]);
@@ -601,6 +603,8 @@ int ipvlan_link_new(struct net *src_net, struct net_device *dev,
                struct ipvl_dev *tmp = netdev_priv(phy_dev);
 
                phy_dev = tmp->phy_dev;
+               if (!ns_capable(dev_net(phy_dev)->user_ns, CAP_NET_ADMIN))
+                       return -EPERM;
        } else if (!netif_is_ipvlan_port(phy_dev)) {
                /* Exit early if the underlying link is invalid or busy */
                if (phy_dev->type != ARPHRD_ETHER ||
index fc726ce..6d06717 100644 (file)
@@ -337,7 +337,7 @@ static void macvlan_process_broadcast(struct work_struct *w)
 
                if (src)
                        dev_put(src->dev);
-               kfree_skb(skb);
+               consume_skb(skb);
        }
 }
 
index 8ebe7f5..f14ba53 100644 (file)
@@ -1,13 +1,7 @@
-// SPDX-License-Identifier: GPL-2.0
+// SPDX-License-Identifier: GPL-2.0+
 /* Driver for Asix PHYs
  *
  * Author: Michael Schmitz <schmitzmic@gmail.com>
- *
- * This program is free software; you can redistribute  it and/or modify it
- * under  the terms of  the GNU General  Public License as published by the
- * Free Software Foundation;  either version 2 of the  License, or (at your
- * option) any later version.
- *
  */
 #include <linux/kernel.h>
 #include <linux/errno.h>
index 1b35018..a271239 100644 (file)
@@ -197,6 +197,7 @@ static struct phy_driver bcm87xx_driver[] = {
        .phy_id         = PHY_ID_BCM8706,
        .phy_id_mask    = 0xffffffff,
        .name           = "Broadcom BCM8706",
+       .features       = PHY_10GBIT_FEC_FEATURES,
        .config_init    = bcm87xx_config_init,
        .config_aneg    = bcm87xx_config_aneg,
        .read_status    = bcm87xx_read_status,
@@ -208,6 +209,7 @@ static struct phy_driver bcm87xx_driver[] = {
        .phy_id         = PHY_ID_BCM8727,
        .phy_id_mask    = 0xffffffff,
        .name           = "Broadcom BCM8727",
+       .features       = PHY_10GBIT_FEC_FEATURES,
        .config_init    = bcm87xx_config_init,
        .config_aneg    = bcm87xx_config_aneg,
        .read_status    = bcm87xx_read_status,
index 8022cd3..1a4d04a 100644 (file)
@@ -88,6 +88,7 @@ static struct phy_driver cortina_driver[] = {
        .phy_id         = PHY_ID_CS4340,
        .phy_id_mask    = 0xffffffff,
        .name           = "Cortina CS4340",
+       .features       = PHY_10GBIT_FEATURES,
        .config_init    = gen10g_config_init,
        .config_aneg    = gen10g_config_aneg,
        .read_status    = cortina_read_status,
index 18b41bc..6e88072 100644 (file)
@@ -898,14 +898,14 @@ static void decode_txts(struct dp83640_private *dp83640,
                        struct phy_txts *phy_txts)
 {
        struct skb_shared_hwtstamps shhwtstamps;
+       struct dp83640_skb_info *skb_info;
        struct sk_buff *skb;
-       u64 ns;
        u8 overflow;
+       u64 ns;
 
        /* We must already have the skb that triggered this. */
-
+again:
        skb = skb_dequeue(&dp83640->tx_queue);
-
        if (!skb) {
                pr_debug("have timestamp but tx_queue empty\n");
                return;
@@ -920,6 +920,11 @@ static void decode_txts(struct dp83640_private *dp83640,
                }
                return;
        }
+       skb_info = (struct dp83640_skb_info *)skb->cb;
+       if (time_after(jiffies, skb_info->tmo)) {
+               kfree_skb(skb);
+               goto again;
+       }
 
        ns = phy2txts(phy_txts);
        memset(&shhwtstamps, 0, sizeof(shhwtstamps));
@@ -1472,6 +1477,7 @@ static bool dp83640_rxtstamp(struct phy_device *phydev,
 static void dp83640_txtstamp(struct phy_device *phydev,
                             struct sk_buff *skb, int type)
 {
+       struct dp83640_skb_info *skb_info = (struct dp83640_skb_info *)skb->cb;
        struct dp83640_private *dp83640 = phydev->priv;
 
        switch (dp83640->hwts_tx_en) {
@@ -1484,6 +1490,7 @@ static void dp83640_txtstamp(struct phy_device *phydev,
                /* fall through */
        case HWTSTAMP_TX_ON:
                skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
+               skb_info->tmo = jiffies + SKB_TIMESTAMP_TIMEOUT;
                skb_queue_tail(&dp83640->tx_queue, skb);
                break;
 
index a9c7c7f..abb7876 100644 (file)
@@ -847,7 +847,6 @@ static int m88e1510_config_init(struct phy_device *phydev)
 
        /* SGMII-to-Copper mode initialization */
        if (phydev->interface == PHY_INTERFACE_MODE_SGMII) {
-
                /* Select page 18 */
                err = marvell_set_page(phydev, 18);
                if (err < 0)
@@ -870,21 +869,6 @@ static int m88e1510_config_init(struct phy_device *phydev)
                err = marvell_set_page(phydev, MII_MARVELL_COPPER_PAGE);
                if (err < 0)
                        return err;
-
-               /* There appears to be a bug in the 88e1512 when used in
-                * SGMII to copper mode, where the AN advertisement register
-                * clears the pause bits each time a negotiation occurs.
-                * This means we can never be truely sure what was advertised,
-                * so disable Pause support.
-                */
-               linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
-                                  phydev->supported);
-               linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT,
-                                  phydev->supported);
-               linkmode_clear_bit(ETHTOOL_LINK_MODE_Asym_Pause_BIT,
-                                  phydev->advertising);
-               linkmode_clear_bit(ETHTOOL_LINK_MODE_Pause_BIT,
-                                  phydev->advertising);
        }
 
        return m88e1318_config_init(phydev);
@@ -1046,6 +1030,39 @@ static int m88e1145_config_init(struct phy_device *phydev)
        return 0;
 }
 
+/* The VOD can be out of specification on link up. Poke an
+ * undocumented register, in an undocumented page, with a magic value
+ * to fix this.
+ */
+static int m88e6390_errata(struct phy_device *phydev)
+{
+       int err;
+
+       err = phy_write(phydev, MII_BMCR,
+                       BMCR_ANENABLE | BMCR_SPEED1000 | BMCR_FULLDPLX);
+       if (err)
+               return err;
+
+       usleep_range(300, 400);
+
+       err = phy_write_paged(phydev, 0xf8, 0x08, 0x36);
+       if (err)
+               return err;
+
+       return genphy_soft_reset(phydev);
+}
+
+static int m88e6390_config_aneg(struct phy_device *phydev)
+{
+       int err;
+
+       err = m88e6390_errata(phydev);
+       if (err)
+               return err;
+
+       return m88e1510_config_aneg(phydev);
+}
+
 /**
  * fiber_lpa_mod_linkmode_lpa_t
  * @advertising: the linkmode advertisement settings
@@ -1402,7 +1419,7 @@ static int m88e1318_set_wol(struct phy_device *phydev,
                 * before enabling it if !phy_interrupt_is_valid()
                 */
                if (!phy_interrupt_is_valid(phydev))
-                       phy_read(phydev, MII_M1011_IEVENT);
+                       __phy_read(phydev, MII_M1011_IEVENT);
 
                /* Enable the WOL interrupt */
                err = __phy_modify(phydev, MII_88E1318S_PHY_CSIER, 0,
@@ -2283,7 +2300,7 @@ static struct phy_driver marvell_drivers[] = {
                .features = PHY_GBIT_FEATURES,
                .probe = m88e6390_probe,
                .config_init = &marvell_config_init,
-               .config_aneg = &m88e1510_config_aneg,
+               .config_aneg = &m88e6390_config_aneg,
                .read_status = &marvell_read_status,
                .ack_interrupt = &marvell_ack_interrupt,
                .config_intr = &marvell_config_intr,
index 82ab6ed..6bac602 100644 (file)
@@ -26,6 +26,8 @@
 #include <linux/marvell_phy.h>
 #include <linux/phy.h>
 
+#define MDIO_AN_10GBT_CTRL_ADV_NBT_MASK        0x01e0
+
 enum {
        MV_PCS_BASE_T           = 0x0000,
        MV_PCS_BASE_R           = 0x1000,
@@ -386,8 +388,10 @@ static int mv3310_config_aneg(struct phy_device *phydev)
        else
                reg = 0;
 
+       /* Make sure we clear unsupported 2.5G/5G advertising */
        ret = mv3310_modify(phydev, MDIO_MMD_AN, MDIO_AN_10GBT_CTRL,
-                           MDIO_AN_10GBT_CTRL_ADV10G, reg);
+                           MDIO_AN_10GBT_CTRL_ADV10G |
+                           MDIO_AN_10GBT_CTRL_ADV_NBT_MASK, reg);
        if (ret < 0)
                return ret;
        if (ret > 0)
index b03fedd..287f3cc 100644 (file)
@@ -1,20 +1,8 @@
+// SPDX-License-Identifier: GPL-2.0+
 /*
  * Hisilicon Fast Ethernet MDIO Bus Driver
  *
  * Copyright (c) 2016 HiSilicon Technologies Co., Ltd.
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program. If not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/clk.h>
@@ -163,4 +151,4 @@ module_platform_driver(hisi_femac_mdio_driver);
 
 MODULE_DESCRIPTION("Hisilicon Fast Ethernet MAC MDIO interface driver");
 MODULE_AUTHOR("Dongpo Li <lidongpo@hisilicon.com>");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
index 2e59a84..7368616 100644 (file)
@@ -379,7 +379,6 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
        err = device_register(&bus->dev);
        if (err) {
                pr_err("mii_bus %s failed to register\n", bus->id);
-               put_device(&bus->dev);
                return -EINVAL;
        }
 
@@ -390,6 +389,7 @@ int __mdiobus_register(struct mii_bus *bus, struct module *owner)
        if (IS_ERR(gpiod)) {
                dev_err(&bus->dev, "mii_bus %s couldn't get reset GPIO\n",
                        bus->id);
+               device_del(&bus->dev);
                return PTR_ERR(gpiod);
        } else  if (gpiod) {
                bus->reset_gpiod = gpiod;
index b03bcf2..3ddaf95 100644 (file)
@@ -233,6 +233,7 @@ static struct phy_driver meson_gxl_phy[] = {
                .name           = "Meson GXL Internal PHY",
                .features       = PHY_BASIC_FEATURES,
                .flags          = PHY_IS_INTERNAL,
+               .soft_reset     = genphy_soft_reset,
                .config_init    = meson_gxl_config_init,
                .aneg_done      = genphy_aneg_done,
                .read_status    = meson_gxl_read_status,
index c333847..b1f9599 100644 (file)
@@ -1070,6 +1070,7 @@ static struct phy_driver ksphy_driver[] = {
        .driver_data    = &ksz9021_type,
        .probe          = kszphy_probe,
        .config_init    = ksz9031_config_init,
+       .soft_reset     = genphy_soft_reset,
        .read_status    = ksz9031_read_status,
        .ack_interrupt  = kszphy_ack_interrupt,
        .config_intr    = kszphy_config_intr,
@@ -1098,6 +1099,7 @@ static struct phy_driver ksphy_driver[] = {
        .phy_id         = PHY_ID_KSZ8873MLL,
        .phy_id_mask    = MICREL_PHY_ID_MASK,
        .name           = "Micrel KSZ8873MLL Switch",
+       .features       = PHY_BASIC_FEATURES,
        .config_init    = kszphy_config_init,
        .config_aneg    = ksz8873mll_config_aneg,
        .read_status    = ksz8873mll_read_status,
index d33e7b3..c5675df 100644 (file)
@@ -543,13 +543,6 @@ int phy_start_aneg(struct phy_device *phydev)
 
        mutex_lock(&phydev->lock);
 
-       if (!__phy_is_started(phydev)) {
-               WARN(1, "called from state %s\n",
-                    phy_state_to_str(phydev->state));
-               err = -EBUSY;
-               goto out_unlock;
-       }
-
        if (AUTONEG_DISABLE == phydev->autoneg)
                phy_sanitize_settings(phydev);
 
@@ -560,11 +553,13 @@ int phy_start_aneg(struct phy_device *phydev)
        if (err < 0)
                goto out_unlock;
 
-       if (phydev->autoneg == AUTONEG_ENABLE) {
-               err = phy_check_link_status(phydev);
-       } else {
-               phydev->state = PHY_FORCING;
-               phydev->link_timeout = PHY_FORCE_TIMEOUT;
+       if (phy_is_started(phydev)) {
+               if (phydev->autoneg == AUTONEG_ENABLE) {
+                       err = phy_check_link_status(phydev);
+               } else {
+                       phydev->state = PHY_FORCING;
+                       phydev->link_timeout = PHY_FORCE_TIMEOUT;
+               }
        }
 
 out_unlock:
@@ -714,7 +709,7 @@ void phy_stop_machine(struct phy_device *phydev)
        cancel_delayed_work_sync(&phydev->state_queue);
 
        mutex_lock(&phydev->lock);
-       if (__phy_is_started(phydev))
+       if (phy_is_started(phydev))
                phydev->state = PHY_UP;
        mutex_unlock(&phydev->lock);
 }
@@ -767,9 +762,6 @@ static irqreturn_t phy_interrupt(int irq, void *phy_dat)
 {
        struct phy_device *phydev = phy_dat;
 
-       if (!phy_is_started(phydev))
-               return IRQ_NONE;                /* It can't be ours.  */
-
        if (phydev->drv->did_interrupt && !phydev->drv->did_interrupt(phydev))
                return IRQ_NONE;
 
@@ -847,15 +839,14 @@ EXPORT_SYMBOL(phy_stop_interrupts);
  */
 void phy_stop(struct phy_device *phydev)
 {
-       mutex_lock(&phydev->lock);
-
-       if (!__phy_is_started(phydev)) {
+       if (!phy_is_started(phydev)) {
                WARN(1, "called from state %s\n",
                     phy_state_to_str(phydev->state));
-               mutex_unlock(&phydev->lock);
                return;
        }
 
+       mutex_lock(&phydev->lock);
+
        if (phy_interrupt_is_valid(phydev))
                phy_disable_interrupts(phydev);
 
@@ -994,8 +985,10 @@ void phy_state_machine(struct work_struct *work)
         * state machine would be pointless and possibly error prone when
         * called from phy_disconnect() synchronously.
         */
+       mutex_lock(&phydev->lock);
        if (phy_polling_mode(phydev) && phy_is_started(phydev))
                phy_queue_state_machine(phydev, PHY_STATE_TIME);
+       mutex_unlock(&phydev->lock);
 }
 
 /**
index 5199000..46c8672 100644 (file)
@@ -61,6 +61,9 @@ EXPORT_SYMBOL_GPL(phy_gbit_all_ports_features);
 __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features) __ro_after_init;
 EXPORT_SYMBOL_GPL(phy_10gbit_features);
 
+__ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_fec_features) __ro_after_init;
+EXPORT_SYMBOL_GPL(phy_10gbit_fec_features);
+
 static const int phy_basic_ports_array[] = {
        ETHTOOL_LINK_MODE_Autoneg_BIT,
        ETHTOOL_LINK_MODE_TP_BIT,
@@ -109,6 +112,11 @@ const int phy_10gbit_features_array[1] = {
 };
 EXPORT_SYMBOL_GPL(phy_10gbit_features_array);
 
+const int phy_10gbit_fec_features_array[1] = {
+       ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
+};
+EXPORT_SYMBOL_GPL(phy_10gbit_fec_features_array);
+
 __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_init;
 EXPORT_SYMBOL_GPL(phy_10gbit_full_features);
 
@@ -191,6 +199,10 @@ static void features_init(void)
        linkmode_set_bit_array(phy_10gbit_full_features_array,
                               ARRAY_SIZE(phy_10gbit_full_features_array),
                               phy_10gbit_full_features);
+       /* 10G FEC only */
+       linkmode_set_bit_array(phy_10gbit_fec_features_array,
+                              ARRAY_SIZE(phy_10gbit_fec_features_array),
+                              phy_10gbit_fec_features);
 }
 
 void phy_device_free(struct phy_device *phydev)
@@ -2243,6 +2255,11 @@ int phy_driver_register(struct phy_driver *new_driver, struct module *owner)
 {
        int retval;
 
+       if (WARN_ON(!new_driver->features)) {
+               pr_err("%s: Driver features are missing\n", new_driver->name);
+               return -EINVAL;
+       }
+
        new_driver->mdiodrv.flags |= MDIO_DEVICE_IS_PHY;
        new_driver->mdiodrv.driver.name = new_driver->name;
        new_driver->mdiodrv.driver.bus = &mdio_bus_type;
index e7becc7..9388032 100644 (file)
@@ -474,6 +474,17 @@ static void phylink_run_resolve(struct phylink *pl)
                queue_work(system_power_efficient_wq, &pl->resolve);
 }
 
+static void phylink_run_resolve_and_disable(struct phylink *pl, int bit)
+{
+       unsigned long state = pl->phylink_disable_state;
+
+       set_bit(bit, &pl->phylink_disable_state);
+       if (state == 0) {
+               queue_work(system_power_efficient_wq, &pl->resolve);
+               flush_work(&pl->resolve);
+       }
+}
+
 static void phylink_fixed_poll(struct timer_list *t)
 {
        struct phylink *pl = container_of(t, struct phylink, link_poll);
@@ -924,9 +935,7 @@ void phylink_stop(struct phylink *pl)
        if (pl->link_an_mode == MLO_AN_FIXED && !IS_ERR(pl->link_gpio))
                del_timer_sync(&pl->link_poll);
 
-       set_bit(PHYLINK_DISABLE_STOPPED, &pl->phylink_disable_state);
-       queue_work(system_power_efficient_wq, &pl->resolve);
-       flush_work(&pl->resolve);
+       phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_STOPPED);
 }
 EXPORT_SYMBOL_GPL(phylink_stop);
 
@@ -1632,9 +1641,7 @@ static void phylink_sfp_link_down(void *upstream)
 
        ASSERT_RTNL();
 
-       set_bit(PHYLINK_DISABLE_LINK, &pl->phylink_disable_state);
-       queue_work(system_power_efficient_wq, &pl->resolve);
-       flush_work(&pl->resolve);
+       phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_LINK);
 }
 
 static void phylink_sfp_link_up(void *upstream)
index c6010fb..cb4a230 100644 (file)
@@ -282,6 +282,13 @@ static struct phy_driver realtek_drvs[] = {
                .name           = "RTL8366RB Gigabit Ethernet",
                .features       = PHY_GBIT_FEATURES,
                .config_init    = &rtl8366rb_config_init,
+               /* These interrupts are handled by the irq controller
+                * embedded inside the RTL8366RB, they get unmasked when the
+                * irq is requested and ACKed by reading the status register,
+                * which is done by the irqchip code.
+                */
+               .ack_interrupt  = genphy_no_ack_interrupt,
+               .config_intr    = genphy_no_config_intr,
                .suspend        = genphy_suspend,
                .resume         = genphy_resume,
        },
index f1da70b..95abf70 100644 (file)
@@ -1,3 +1,4 @@
+// SPDX-License-Identifier: GPL-2.0+
 /**
  * drivers/net/phy/rockchip.c
  *
@@ -6,12 +7,6 @@
  * Copyright (c) 2017, Fuzhou Rockchip Electronics Co., Ltd
  *
  * David Wu <david.wu@rock-chips.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License as published by
- * the Free Software Foundation; either version 2 of the License, or
- * (at your option) any later version.
- *
  */
 
 #include <linux/ethtool.h>
@@ -229,4 +224,4 @@ MODULE_DEVICE_TABLE(mdio, rockchip_phy_tbl);
 
 MODULE_AUTHOR("David Wu <david.wu@rock-chips.com>");
 MODULE_DESCRIPTION("Rockchip Ethernet PHY driver");
-MODULE_LICENSE("GPL v2");
+MODULE_LICENSE("GPL");
index ad9db65..fef701b 100644 (file)
@@ -347,6 +347,7 @@ static int sfp_register_bus(struct sfp_bus *bus)
                                return ret;
                }
        }
+       bus->socket_ops->attach(bus->sfp);
        if (bus->started)
                bus->socket_ops->start(bus->sfp);
        bus->netdev->sfp_bus = bus;
@@ -362,6 +363,7 @@ static void sfp_unregister_bus(struct sfp_bus *bus)
        if (bus->registered) {
                if (bus->started)
                        bus->socket_ops->stop(bus->sfp);
+               bus->socket_ops->detach(bus->sfp);
                if (bus->phydev && ops && ops->disconnect_phy)
                        ops->disconnect_phy(bus->upstream);
        }
index fd8bb99..68c8fbf 100644 (file)
@@ -184,6 +184,7 @@ struct sfp {
 
        struct gpio_desc *gpio[GPIO_MAX];
 
+       bool attached;
        unsigned int state;
        struct delayed_work poll;
        struct delayed_work timeout;
@@ -1475,7 +1476,7 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
         */
        switch (sfp->sm_mod_state) {
        default:
-               if (event == SFP_E_INSERT) {
+               if (event == SFP_E_INSERT && sfp->attached) {
                        sfp_module_tx_disable(sfp);
                        sfp_sm_ins_next(sfp, SFP_MOD_PROBE, T_PROBE_INIT);
                }
@@ -1607,6 +1608,19 @@ static void sfp_sm_event(struct sfp *sfp, unsigned int event)
        mutex_unlock(&sfp->sm_mutex);
 }
 
+static void sfp_attach(struct sfp *sfp)
+{
+       sfp->attached = true;
+       if (sfp->state & SFP_F_PRESENT)
+               sfp_sm_event(sfp, SFP_E_INSERT);
+}
+
+static void sfp_detach(struct sfp *sfp)
+{
+       sfp->attached = false;
+       sfp_sm_event(sfp, SFP_E_REMOVE);
+}
+
 static void sfp_start(struct sfp *sfp)
 {
        sfp_sm_event(sfp, SFP_E_DEV_UP);
@@ -1667,6 +1681,8 @@ static int sfp_module_eeprom(struct sfp *sfp, struct ethtool_eeprom *ee,
 }
 
 static const struct sfp_socket_ops sfp_module_ops = {
+       .attach = sfp_attach,
+       .detach = sfp_detach,
        .start = sfp_start,
        .stop = sfp_stop,
        .module_info = sfp_module_info,
@@ -1834,10 +1850,6 @@ static int sfp_probe(struct platform_device *pdev)
        dev_info(sfp->dev, "Host maximum power %u.%uW\n",
                 sfp->max_power_mW / 1000, (sfp->max_power_mW / 100) % 10);
 
-       sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops);
-       if (!sfp->sfp_bus)
-               return -ENOMEM;
-
        /* Get the initial state, and always signal TX disable,
         * since the network interface will not be up.
         */
@@ -1848,10 +1860,6 @@ static int sfp_probe(struct platform_device *pdev)
                sfp->state |= SFP_F_RATE_SELECT;
        sfp_set_state(sfp, sfp->state);
        sfp_module_tx_disable(sfp);
-       rtnl_lock();
-       if (sfp->state & SFP_F_PRESENT)
-               sfp_sm_event(sfp, SFP_E_INSERT);
-       rtnl_unlock();
 
        for (i = 0; i < GPIO_MAX; i++) {
                if (gpio_flags[i] != GPIOD_IN || !sfp->gpio[i])
@@ -1884,6 +1892,10 @@ static int sfp_probe(struct platform_device *pdev)
                dev_warn(sfp->dev,
                         "No tx_disable pin: SFP modules will always be emitting.\n");
 
+       sfp->sfp_bus = sfp_register_socket(sfp->dev, sfp, &sfp_module_ops);
+       if (!sfp->sfp_bus)
+               return -ENOMEM;
+
        return 0;
 }
 
index 31b0acf..64f54b0 100644 (file)
@@ -7,6 +7,8 @@
 struct sfp;
 
 struct sfp_socket_ops {
+       void (*attach)(struct sfp *sfp);
+       void (*detach)(struct sfp *sfp);
        void (*start)(struct sfp *sfp);
        void (*stop)(struct sfp *sfp);
        int (*module_info)(struct sfp *sfp, struct ethtool_modinfo *modinfo);
index 22f3bdd..9124718 100644 (file)
@@ -80,6 +80,7 @@ static struct phy_driver teranetics_driver[] = {
        .phy_id         = PHY_ID_TN2020,
        .phy_id_mask    = 0xffffffff,
        .name           = "Teranetics TN2020",
+       .features       = PHY_10GBIT_FEATURES,
        .soft_reset     = gen10g_no_soft_reset,
        .aneg_done      = teranetics_aneg_done,
        .config_init    = gen10g_config_init,
index 74a8782..bd6084e 100644 (file)
@@ -44,7 +44,10 @@ static int xgmiitorgmii_read_status(struct phy_device *phydev)
        u16 val = 0;
        int err;
 
-       err = priv->phy_drv->read_status(phydev);
+       if (priv->phy_drv->read_status)
+               err = priv->phy_drv->read_status(phydev);
+       else
+               err = genphy_read_status(phydev);
        if (err < 0)
                return err;
 
index 62dc564..f22639f 100644 (file)
@@ -445,6 +445,7 @@ static int pppoe_rcv(struct sk_buff *skb, struct net_device *dev,
        if (pskb_trim_rcsum(skb, len))
                goto drop;
 
+       ph = pppoe_hdr(skb);
        pn = pppoe_pernet(dev_net(dev));
 
        /* Note that get_item does a sock_hold(), so sk_pppox(po)
index afd9d25..6ce3f66 100644 (file)
@@ -256,17 +256,6 @@ static void __team_option_inst_mark_removed_port(struct team *team,
        }
 }
 
-static bool __team_option_inst_tmp_find(const struct list_head *opts,
-                                       const struct team_option_inst *needle)
-{
-       struct team_option_inst *opt_inst;
-
-       list_for_each_entry(opt_inst, opts, tmp_list)
-               if (opt_inst == needle)
-                       return true;
-       return false;
-}
-
 static int __team_options_register(struct team *team,
                                   const struct team_option *option,
                                   size_t option_count)
@@ -1267,7 +1256,7 @@ static int team_port_add(struct team *team, struct net_device *port_dev,
        list_add_tail_rcu(&port->list, &team->port_list);
        team_port_enable(team, port);
        __team_compute_features(team);
-       __team_port_change_port_added(port, !!netif_carrier_ok(port_dev));
+       __team_port_change_port_added(port, !!netif_oper_up(port_dev));
        __team_options_change_check(team);
 
        netdev_info(dev, "Port device %s added\n", portname);
@@ -2460,7 +2449,6 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
        int err = 0;
        int i;
        struct nlattr *nl_option;
-       LIST_HEAD(opt_inst_list);
 
        rtnl_lock();
 
@@ -2480,6 +2468,7 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
                struct nlattr *opt_attrs[TEAM_ATTR_OPTION_MAX + 1];
                struct nlattr *attr;
                struct nlattr *attr_data;
+               LIST_HEAD(opt_inst_list);
                enum team_option_type opt_type;
                int opt_port_ifindex = 0; /* != 0 for per-port options */
                u32 opt_array_index = 0;
@@ -2584,23 +2573,17 @@ static int team_nl_cmd_options_set(struct sk_buff *skb, struct genl_info *info)
                        if (err)
                                goto team_put;
                        opt_inst->changed = true;
-
-                       /* dumb/evil user-space can send us duplicate opt,
-                        * keep only the last one
-                        */
-                       if (__team_option_inst_tmp_find(&opt_inst_list,
-                                                       opt_inst))
-                               continue;
-
                        list_add(&opt_inst->tmp_list, &opt_inst_list);
                }
                if (!opt_found) {
                        err = -ENOENT;
                        goto team_put;
                }
-       }
 
-       err = team_nl_send_event_options_get(team, &opt_inst_list);
+               err = team_nl_send_event_options_get(team, &opt_inst_list);
+               if (err)
+                       break;
+       }
 
 team_put:
        team_nl_team_put(team);
@@ -2932,7 +2915,7 @@ static int team_device_event(struct notifier_block *unused,
 
        switch (event) {
        case NETDEV_UP:
-               if (netif_carrier_ok(dev))
+               if (netif_oper_up(dev))
                        team_port_change_check(port, true);
                break;
        case NETDEV_DOWN:
index a4fdad4..fed298c 100644 (file)
@@ -856,10 +856,6 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
                err = 0;
        }
 
-       rcu_assign_pointer(tfile->tun, tun);
-       rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
-       tun->numqueues++;
-
        if (tfile->detached) {
                tun_enable_queue(tfile);
        } else {
@@ -870,12 +866,18 @@ static int tun_attach(struct tun_struct *tun, struct file *file,
        if (rtnl_dereference(tun->xdp_prog))
                sock_set_flag(&tfile->sk, SOCK_XDP);
 
-       tun_set_real_num_queues(tun);
-
        /* device is allowed to go away first, so no need to hold extra
         * refcnt.
         */
 
+       /* Publish tfile->tun and tun->tfiles only after we've fully
+        * initialized tfile; otherwise we risk using half-initialized
+        * object.
+        */
+       rcu_assign_pointer(tfile->tun, tun);
+       rcu_assign_pointer(tun->tfiles[tun->numqueues], tfile);
+       tun->numqueues++;
+       tun_set_real_num_queues(tun);
 out:
        return err;
 }
index 57f1c94..820a2fe 100644 (file)
@@ -1287,6 +1287,20 @@ static const struct driver_info asix112_info = {
 
 #undef ASIX112_DESC
 
+static const struct driver_info trendnet_info = {
+       .description    = "USB-C 3.1 to 5GBASE-T Ethernet Adapter",
+       .bind           = aqc111_bind,
+       .unbind         = aqc111_unbind,
+       .status         = aqc111_status,
+       .link_reset     = aqc111_link_reset,
+       .reset          = aqc111_reset,
+       .stop           = aqc111_stop,
+       .flags          = FLAG_ETHER | FLAG_FRAMING_AX |
+                         FLAG_AVOID_UNLINK_URBS | FLAG_MULTI_PACKET,
+       .rx_fixup       = aqc111_rx_fixup,
+       .tx_fixup       = aqc111_tx_fixup,
+};
+
 static int aqc111_suspend(struct usb_interface *intf, pm_message_t message)
 {
        struct usbnet *dev = usb_get_intfdata(intf);
@@ -1440,6 +1454,7 @@ static const struct usb_device_id products[] = {
        {AQC111_USB_ETH_DEV(0x2eca, 0xc101, aqc111_info)},
        {AQC111_USB_ETH_DEV(0x0b95, 0x2790, asix111_info)},
        {AQC111_USB_ETH_DEV(0x0b95, 0x2791, asix112_info)},
+       {AQC111_USB_ETH_DEV(0x20f4, 0xe05a, trendnet_info)},
        { },/* END */
 };
 MODULE_DEVICE_TABLE(usb, products);
index b654f05..3d93993 100644 (file)
@@ -739,8 +739,13 @@ static int ax88772_bind(struct usbnet *dev, struct usb_interface *intf)
        asix_read_cmd(dev, AX_CMD_STATMNGSTS_REG, 0, 0, 1, &chipcode, 0);
        chipcode &= AX_CHIPCODE_MASK;
 
-       (chipcode == AX_AX88772_CHIPCODE) ? ax88772_hw_reset(dev, 0) :
-                                           ax88772a_hw_reset(dev, 0);
+       ret = (chipcode == AX_AX88772_CHIPCODE) ? ax88772_hw_reset(dev, 0) :
+                                                 ax88772a_hw_reset(dev, 0);
+
+       if (ret < 0) {
+               netdev_dbg(dev->net, "Failed to reset AX88772: %d\n", ret);
+               return ret;
+       }
 
        /* Read PHYID register *AFTER* the PHY was reset properly */
        phyid = asix_get_phyid(dev);
index b3b3c05..5512a10 100644 (file)
@@ -179,10 +179,8 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
         * probed with) and a slave/data interface; union
         * descriptors sort this all out.
         */
-       info->control = usb_ifnum_to_if(dev->udev,
-       info->u->bMasterInterface0);
-       info->data = usb_ifnum_to_if(dev->udev,
-               info->u->bSlaveInterface0);
+       info->control = usb_ifnum_to_if(dev->udev, info->u->bMasterInterface0);
+       info->data = usb_ifnum_to_if(dev->udev, info->u->bSlaveInterface0);
        if (!info->control || !info->data) {
                dev_dbg(&intf->dev,
                        "master #%u/%p slave #%u/%p\n",
@@ -216,18 +214,16 @@ int usbnet_generic_cdc_bind(struct usbnet *dev, struct usb_interface *intf)
        /* a data interface altsetting does the real i/o */
        d = &info->data->cur_altsetting->desc;
        if (d->bInterfaceClass != USB_CLASS_CDC_DATA) {
-               dev_dbg(&intf->dev, "slave class %u\n",
-                       d->bInterfaceClass);
+               dev_dbg(&intf->dev, "slave class %u\n", d->bInterfaceClass);
                goto bad_desc;
        }
 skip:
-       if (    rndis &&
-               header.usb_cdc_acm_descriptor &&
-               header.usb_cdc_acm_descriptor->bmCapabilities) {
-                       dev_dbg(&intf->dev,
-                               "ACM capabilities %02x, not really RNDIS?\n",
-                               header.usb_cdc_acm_descriptor->bmCapabilities);
-                       goto bad_desc;
+       if (rndis && header.usb_cdc_acm_descriptor &&
+           header.usb_cdc_acm_descriptor->bmCapabilities) {
+               dev_dbg(&intf->dev,
+                       "ACM capabilities %02x, not really RNDIS?\n",
+                       header.usb_cdc_acm_descriptor->bmCapabilities);
+               goto bad_desc;
        }
 
        if (header.usb_cdc_ether_desc && info->ether->wMaxSegmentSize) {
@@ -238,7 +234,7 @@ skip:
        }
 
        if (header.usb_cdc_mdlm_desc &&
-               memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) {
+           memcmp(header.usb_cdc_mdlm_desc->bGUID, mbm_guid, 16)) {
                dev_dbg(&intf->dev, "GUID doesn't match\n");
                goto bad_desc;
        }
@@ -302,7 +298,7 @@ skip:
        if (info->control->cur_altsetting->desc.bNumEndpoints == 1) {
                struct usb_endpoint_descriptor  *desc;
 
-               dev->status = &info->control->cur_altsetting->endpoint [0];
+               dev->status = &info->control->cur_altsetting->endpoint[0];
                desc = &dev->status->desc;
                if (!usb_endpoint_is_int_in(desc) ||
                    (le16_to_cpu(desc->wMaxPacketSize)
@@ -847,6 +843,14 @@ static const struct usb_device_id  products[] = {
        .driver_info = 0,
 },
 
+/* USB-C 3.1 to 5GBASE-T Ethernet Adapter (based on AQC111U) */
+{
+       USB_DEVICE_AND_INTERFACE_INFO(0x20f4, 0xe05a, USB_CLASS_COMM,
+                                     USB_CDC_SUBCLASS_ETHERNET,
+                                     USB_CDC_PROTO_NONE),
+       .driver_info = 0,
+},
+
 /* WHITELIST!!!
  *
  * CDC Ether uses two interfaces, not necessarily consecutive.
index 774e1ff..18af2f8 100644 (file)
@@ -123,6 +123,7 @@ static void qmimux_setup(struct net_device *dev)
        dev->addr_len        = 0;
        dev->flags           = IFF_POINTOPOINT | IFF_NOARP | IFF_MULTICAST;
        dev->netdev_ops      = &qmimux_netdev_ops;
+       dev->mtu             = 1500;
        dev->needs_free_netdev = true;
 }
 
@@ -1200,8 +1201,8 @@ static const struct usb_device_id products[] = {
        {QMI_FIXED_INTF(0x114f, 0x68a2, 8)},    /* Sierra Wireless MC7750 */
        {QMI_FIXED_INTF(0x1199, 0x68a2, 8)},    /* Sierra Wireless MC7710 in QMI mode */
        {QMI_FIXED_INTF(0x1199, 0x68a2, 19)},   /* Sierra Wireless MC7710 in QMI mode */
-       {QMI_FIXED_INTF(0x1199, 0x68c0, 8)},    /* Sierra Wireless MC7304/MC7354 */
-       {QMI_FIXED_INTF(0x1199, 0x68c0, 10)},   /* Sierra Wireless MC7304/MC7354 */
+       {QMI_QUIRK_SET_DTR(0x1199, 0x68c0, 8)}, /* Sierra Wireless MC7304/MC7354, WP76xx */
+       {QMI_QUIRK_SET_DTR(0x1199, 0x68c0, 10)},/* Sierra Wireless MC7304/MC7354 */
        {QMI_FIXED_INTF(0x1199, 0x901c, 8)},    /* Sierra Wireless EM7700 */
        {QMI_FIXED_INTF(0x1199, 0x901f, 8)},    /* Sierra Wireless EM7355 */
        {QMI_FIXED_INTF(0x1199, 0x9041, 8)},    /* Sierra Wireless MC7305/MC7355 */
index 60dd1ec..86c8c64 100644 (file)
@@ -557,6 +557,7 @@ enum spd_duplex {
 /* MAC PASSTHRU */
 #define AD_MASK                        0xfee0
 #define BND_MASK               0x0004
+#define BD_MASK                        0x0001
 #define EFUSE                  0xcfdb
 #define PASS_THRU_MASK         0x1
 
@@ -1176,9 +1177,9 @@ static int vendor_mac_passthru_addr_read(struct r8152 *tp, struct sockaddr *sa)
                        return -ENODEV;
                }
        } else {
-               /* test for RTL8153-BND */
+               /* test for RTL8153-BND and RTL8153-BD */
                ocp_data = ocp_read_byte(tp, MCU_TYPE_USB, USB_MISC_1);
-               if ((ocp_data & BND_MASK) == 0) {
+               if ((ocp_data & BND_MASK) == 0 && (ocp_data & BD_MASK) == 0) {
                        netif_dbg(tp, probe, tp->netdev,
                                  "Invalid variant for MAC pass through\n");
                        return -ENODEV;
index 0237250..4cfceb7 100644 (file)
@@ -57,6 +57,8 @@ module_param(napi_tx, bool, 0644);
 #define VIRTIO_XDP_TX          BIT(0)
 #define VIRTIO_XDP_REDIR       BIT(1)
 
+#define VIRTIO_XDP_FLAG        BIT(0)
+
 /* RX packet size EWMA. The average packet size is used to determine the packet
  * buffer size when refilling RX rings. As the entire RX ring may be refilled
  * at once, the weight is chosen so that the EWMA will be insensitive to short-
@@ -252,6 +254,21 @@ struct padded_vnet_hdr {
        char padding[4];
 };
 
+static bool is_xdp_frame(void *ptr)
+{
+       return (unsigned long)ptr & VIRTIO_XDP_FLAG;
+}
+
+static void *xdp_to_ptr(struct xdp_frame *ptr)
+{
+       return (void *)((unsigned long)ptr | VIRTIO_XDP_FLAG);
+}
+
+static struct xdp_frame *ptr_to_xdp(void *ptr)
+{
+       return (struct xdp_frame *)((unsigned long)ptr & ~VIRTIO_XDP_FLAG);
+}
+
 /* Converting between virtqueue no. and kernel tx/rx queue no.
  * 0:rx0 1:tx0 2:rx1 3:tx1 ... 2N:rxN 2N+1:txN 2N+2:cvq
  */
@@ -462,7 +479,8 @@ static int __virtnet_xdp_xmit_one(struct virtnet_info *vi,
 
        sg_init_one(sq->sg, xdpf->data, xdpf->len);
 
-       err = virtqueue_add_outbuf(sq->vq, sq->sg, 1, xdpf, GFP_ATOMIC);
+       err = virtqueue_add_outbuf(sq->vq, sq->sg, 1, xdp_to_ptr(xdpf),
+                                  GFP_ATOMIC);
        if (unlikely(err))
                return -ENOSPC; /* Caller handle free/refcnt */
 
@@ -482,36 +500,47 @@ static int virtnet_xdp_xmit(struct net_device *dev,
 {
        struct virtnet_info *vi = netdev_priv(dev);
        struct receive_queue *rq = vi->rq;
-       struct xdp_frame *xdpf_sent;
        struct bpf_prog *xdp_prog;
        struct send_queue *sq;
        unsigned int len;
+       int packets = 0;
+       int bytes = 0;
        int drops = 0;
        int kicks = 0;
        int ret, err;
+       void *ptr;
        int i;
 
-       sq = virtnet_xdp_sq(vi);
-
-       if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) {
-               ret = -EINVAL;
-               drops = n;
-               goto out;
-       }
-
        /* Only allow ndo_xdp_xmit if XDP is loaded on dev, as this
         * indicate XDP resources have been successfully allocated.
         */
        xdp_prog = rcu_dereference(rq->xdp_prog);
-       if (!xdp_prog) {
-               ret = -ENXIO;
+       if (!xdp_prog)
+               return -ENXIO;
+
+       sq = virtnet_xdp_sq(vi);
+
+       if (unlikely(flags & ~XDP_XMIT_FLAGS_MASK)) {
+               ret = -EINVAL;
                drops = n;
                goto out;
        }
 
        /* Free up any pending old buffers before queueing new ones. */
-       while ((xdpf_sent = virtqueue_get_buf(sq->vq, &len)) != NULL)
-               xdp_return_frame(xdpf_sent);
+       while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
+               if (likely(is_xdp_frame(ptr))) {
+                       struct xdp_frame *frame = ptr_to_xdp(ptr);
+
+                       bytes += frame->len;
+                       xdp_return_frame(frame);
+               } else {
+                       struct sk_buff *skb = ptr;
+
+                       bytes += skb->len;
+                       napi_consume_skb(skb, false);
+               }
+               packets++;
+       }
 
        for (i = 0; i < n; i++) {
                struct xdp_frame *xdpf = frames[i];
@@ -530,6 +559,8 @@ static int virtnet_xdp_xmit(struct net_device *dev,
        }
 out:
        u64_stats_update_begin(&sq->stats.syncp);
+       sq->stats.bytes += bytes;
+       sq->stats.packets += packets;
        sq->stats.xdp_tx += n;
        sq->stats.xdp_tx_drops += drops;
        sq->stats.kicks += kicks;
@@ -1330,20 +1361,28 @@ static int virtnet_receive(struct receive_queue *rq, int budget,
        return stats.packets;
 }
 
-static void free_old_xmit_skbs(struct send_queue *sq)
+static void free_old_xmit_skbs(struct send_queue *sq, bool in_napi)
 {
-       struct sk_buff *skb;
        unsigned int len;
        unsigned int packets = 0;
        unsigned int bytes = 0;
+       void *ptr;
 
-       while ((skb = virtqueue_get_buf(sq->vq, &len)) != NULL) {
-               pr_debug("Sent skb %p\n", skb);
+       while ((ptr = virtqueue_get_buf(sq->vq, &len)) != NULL) {
+               if (likely(!is_xdp_frame(ptr))) {
+                       struct sk_buff *skb = ptr;
 
-               bytes += skb->len;
-               packets++;
+                       pr_debug("Sent skb %p\n", skb);
+
+                       bytes += skb->len;
+                       napi_consume_skb(skb, in_napi);
+               } else {
+                       struct xdp_frame *frame = ptr_to_xdp(ptr);
 
-               dev_consume_skb_any(skb);
+                       bytes += frame->len;
+                       xdp_return_frame(frame);
+               }
+               packets++;
        }
 
        /* Avoid overhead when no packets have been processed
@@ -1358,6 +1397,16 @@ static void free_old_xmit_skbs(struct send_queue *sq)
        u64_stats_update_end(&sq->stats.syncp);
 }
 
+static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q)
+{
+       if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
+               return false;
+       else if (q < vi->curr_queue_pairs)
+               return true;
+       else
+               return false;
+}
+
 static void virtnet_poll_cleantx(struct receive_queue *rq)
 {
        struct virtnet_info *vi = rq->vq->vdev->priv;
@@ -1365,11 +1414,11 @@ static void virtnet_poll_cleantx(struct receive_queue *rq)
        struct send_queue *sq = &vi->sq[index];
        struct netdev_queue *txq = netdev_get_tx_queue(vi->dev, index);
 
-       if (!sq->napi.weight)
+       if (!sq->napi.weight || is_xdp_raw_buffer_queue(vi, index))
                return;
 
        if (__netif_tx_trylock(txq)) {
-               free_old_xmit_skbs(sq);
+               free_old_xmit_skbs(sq, true);
                __netif_tx_unlock(txq);
        }
 
@@ -1442,10 +1491,18 @@ static int virtnet_poll_tx(struct napi_struct *napi, int budget)
 {
        struct send_queue *sq = container_of(napi, struct send_queue, napi);
        struct virtnet_info *vi = sq->vq->vdev->priv;
-       struct netdev_queue *txq = netdev_get_tx_queue(vi->dev, vq2txq(sq->vq));
+       unsigned int index = vq2txq(sq->vq);
+       struct netdev_queue *txq;
 
+       if (unlikely(is_xdp_raw_buffer_queue(vi, index))) {
+               /* We don't need to enable cb for XDP */
+               napi_complete_done(napi, 0);
+               return 0;
+       }
+
+       txq = netdev_get_tx_queue(vi->dev, index);
        __netif_tx_lock(txq, raw_smp_processor_id());
-       free_old_xmit_skbs(sq);
+       free_old_xmit_skbs(sq, true);
        __netif_tx_unlock(txq);
 
        virtqueue_napi_complete(napi, sq->vq, 0);
@@ -1514,7 +1571,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
        bool use_napi = sq->napi.weight;
 
        /* Free up any pending old buffers before queueing new ones. */
-       free_old_xmit_skbs(sq);
+       free_old_xmit_skbs(sq, false);
 
        if (use_napi && kick)
                virtqueue_enable_cb_delayed(sq->vq);
@@ -1557,7 +1614,7 @@ static netdev_tx_t start_xmit(struct sk_buff *skb, struct net_device *dev)
                if (!use_napi &&
                    unlikely(!virtqueue_enable_cb_delayed(sq->vq))) {
                        /* More just got used, free them then recheck. */
-                       free_old_xmit_skbs(sq);
+                       free_old_xmit_skbs(sq, false);
                        if (sq->vq->num_free >= 2+MAX_SKB_FRAGS) {
                                netif_start_subqueue(dev, qnum);
                                virtqueue_disable_cb(sq->vq);
@@ -2395,6 +2452,10 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
                return -ENOMEM;
        }
 
+       old_prog = rtnl_dereference(vi->rq[0].xdp_prog);
+       if (!prog && !old_prog)
+               return 0;
+
        if (prog) {
                prog = bpf_prog_add(prog, vi->max_queue_pairs - 1);
                if (IS_ERR(prog))
@@ -2402,36 +2463,62 @@ static int virtnet_xdp_set(struct net_device *dev, struct bpf_prog *prog,
        }
 
        /* Make sure NAPI is not using any XDP TX queues for RX. */
-       if (netif_running(dev))
-               for (i = 0; i < vi->max_queue_pairs; i++)
+       if (netif_running(dev)) {
+               for (i = 0; i < vi->max_queue_pairs; i++) {
                        napi_disable(&vi->rq[i].napi);
+                       virtnet_napi_tx_disable(&vi->sq[i].napi);
+               }
+       }
+
+       if (!prog) {
+               for (i = 0; i < vi->max_queue_pairs; i++) {
+                       rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
+                       if (i == 0)
+                               virtnet_restore_guest_offloads(vi);
+               }
+               synchronize_net();
+       }
 
-       netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp);
        err = _virtnet_set_queues(vi, curr_qp + xdp_qp);
        if (err)
                goto err;
+       netif_set_real_num_rx_queues(dev, curr_qp + xdp_qp);
        vi->xdp_queue_pairs = xdp_qp;
 
-       for (i = 0; i < vi->max_queue_pairs; i++) {
-               old_prog = rtnl_dereference(vi->rq[i].xdp_prog);
-               rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
-               if (i == 0) {
-                       if (!old_prog)
+       if (prog) {
+               for (i = 0; i < vi->max_queue_pairs; i++) {
+                       rcu_assign_pointer(vi->rq[i].xdp_prog, prog);
+                       if (i == 0 && !old_prog)
                                virtnet_clear_guest_offloads(vi);
-                       if (!prog)
-                               virtnet_restore_guest_offloads(vi);
                }
+       }
+
+       for (i = 0; i < vi->max_queue_pairs; i++) {
                if (old_prog)
                        bpf_prog_put(old_prog);
-               if (netif_running(dev))
+               if (netif_running(dev)) {
                        virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
+                       virtnet_napi_tx_enable(vi, vi->sq[i].vq,
+                                              &vi->sq[i].napi);
+               }
        }
 
        return 0;
 
 err:
-       for (i = 0; i < vi->max_queue_pairs; i++)
-               virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
+       if (!prog) {
+               virtnet_clear_guest_offloads(vi);
+               for (i = 0; i < vi->max_queue_pairs; i++)
+                       rcu_assign_pointer(vi->rq[i].xdp_prog, old_prog);
+       }
+
+       if (netif_running(dev)) {
+               for (i = 0; i < vi->max_queue_pairs; i++) {
+                       virtnet_napi_enable(vi->rq[i].vq, &vi->rq[i].napi);
+                       virtnet_napi_tx_enable(vi, vi->sq[i].vq,
+                                              &vi->sq[i].napi);
+               }
+       }
        if (prog)
                bpf_prog_sub(prog, vi->max_queue_pairs - 1);
        return err;
@@ -2613,16 +2700,6 @@ static void free_receive_page_frags(struct virtnet_info *vi)
                        put_page(vi->rq[i].alloc_frag.page);
 }
 
-static bool is_xdp_raw_buffer_queue(struct virtnet_info *vi, int q)
-{
-       if (q < (vi->curr_queue_pairs - vi->xdp_queue_pairs))
-               return false;
-       else if (q < vi->curr_queue_pairs)
-               return true;
-       else
-               return false;
-}
-
 static void free_unused_bufs(struct virtnet_info *vi)
 {
        void *buf;
@@ -2631,10 +2708,10 @@ static void free_unused_bufs(struct virtnet_info *vi)
        for (i = 0; i < vi->max_queue_pairs; i++) {
                struct virtqueue *vq = vi->sq[i].vq;
                while ((buf = virtqueue_detach_unused_buf(vq)) != NULL) {
-                       if (!is_xdp_raw_buffer_queue(vi, i))
+                       if (!is_xdp_frame(buf))
                                dev_kfree_skb(buf);
                        else
-                               put_page(virt_to_head_page(buf));
+                               xdp_return_frame(ptr_to_xdp(buf));
                }
        }
 
index e454dfc..89984fc 100644 (file)
@@ -535,8 +535,8 @@ vmxnet3_tq_create(struct vmxnet3_tx_queue *tq,
        }
 
        sz = tq->tx_ring.size * sizeof(tq->buf_info[0]);
-       tq->buf_info = dma_zalloc_coherent(&adapter->pdev->dev, sz,
-                                          &tq->buf_info_pa, GFP_KERNEL);
+       tq->buf_info = dma_alloc_coherent(&adapter->pdev->dev, sz,
+                                         &tq->buf_info_pa, GFP_KERNEL);
        if (!tq->buf_info)
                goto err;
 
@@ -1815,8 +1815,8 @@ vmxnet3_rq_create(struct vmxnet3_rx_queue *rq, struct vmxnet3_adapter *adapter)
 
        sz = sizeof(struct vmxnet3_rx_buf_info) * (rq->rx_ring[0].size +
                                                   rq->rx_ring[1].size);
-       bi = dma_zalloc_coherent(&adapter->pdev->dev, sz, &rq->buf_info_pa,
-                                GFP_KERNEL);
+       bi = dma_alloc_coherent(&adapter->pdev->dev, sz, &rq->buf_info_pa,
+                               GFP_KERNEL);
        if (!bi)
                goto err;
 
index 95909e2..7c1430e 100644 (file)
@@ -1273,6 +1273,9 @@ static void vrf_setup(struct net_device *dev)
 
        /* default to no qdisc; user can add if desired */
        dev->priv_flags |= IFF_NO_QUEUE;
+
+       dev->min_mtu = 0;
+       dev->max_mtu = 0;
 }
 
 static int vrf_validate(struct nlattr *tb[], struct nlattr *data[],
index 5209ee9..2aae11f 100644 (file)
@@ -2219,7 +2219,7 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
        struct pcpu_sw_netstats *tx_stats, *rx_stats;
        union vxlan_addr loopback;
        union vxlan_addr *remote_ip = &dst_vxlan->default_dst.remote_ip;
-       struct net_device *dev = skb->dev;
+       struct net_device *dev;
        int len = skb->len;
 
        tx_stats = this_cpu_ptr(src_vxlan->dev->tstats);
@@ -2239,9 +2239,15 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
 #endif
        }
 
+       rcu_read_lock();
+       dev = skb->dev;
+       if (unlikely(!(dev->flags & IFF_UP))) {
+               kfree_skb(skb);
+               goto drop;
+       }
+
        if (dst_vxlan->cfg.flags & VXLAN_F_LEARN)
-               vxlan_snoop(skb->dev, &loopback, eth_hdr(skb)->h_source, 0,
-                           vni);
+               vxlan_snoop(dev, &loopback, eth_hdr(skb)->h_source, 0, vni);
 
        u64_stats_update_begin(&tx_stats->syncp);
        tx_stats->tx_packets++;
@@ -2254,8 +2260,10 @@ static void vxlan_encap_bypass(struct sk_buff *skb, struct vxlan_dev *src_vxlan,
                rx_stats->rx_bytes += len;
                u64_stats_update_end(&rx_stats->syncp);
        } else {
+drop:
                dev->stats.rx_dropped++;
        }
+       rcu_read_unlock();
 }
 
 static int encap_bypass_if_local(struct sk_buff *skb, struct net_device *dev,
index c0b0f52..27decf8 100644 (file)
@@ -1575,7 +1575,7 @@ try:
                                        dev->stats.tx_packets++;
                                        dev->stats.tx_bytes += skb->len;
                                }
-                               dev_kfree_skb_irq(skb);
+                               dev_consume_skb_irq(skb);
                                dpriv->tx_skbuff[cur] = NULL;
                                ++dpriv->tx_dirty;
                        } else {
index 839fa77..a08f04c 100644 (file)
@@ -279,10 +279,9 @@ static int uhdlc_init(struct ucc_hdlc_private *priv)
        iowrite16be(DEFAULT_HDLC_ADDR, &priv->ucc_pram->haddr4);
 
        /* Get BD buffer */
-       bd_buffer = dma_zalloc_coherent(priv->dev,
-                                       (RX_BD_RING_LEN + TX_BD_RING_LEN) *
-                                       MAX_RX_BUF_LENGTH,
-                                       &bd_dma_addr, GFP_KERNEL);
+       bd_buffer = dma_alloc_coherent(priv->dev,
+                                      (RX_BD_RING_LEN + TX_BD_RING_LEN) * MAX_RX_BUF_LENGTH,
+                                      &bd_dma_addr, GFP_KERNEL);
 
        if (!bd_buffer) {
                dev_err(priv->dev, "Could not allocate buffer descriptors\n");
@@ -483,7 +482,7 @@ static int hdlc_tx_done(struct ucc_hdlc_private *priv)
                memset(priv->tx_buffer +
                       (be32_to_cpu(bd->buf) - priv->dma_tx_addr),
                       0, skb->len);
-               dev_kfree_skb_irq(skb);
+               dev_consume_skb_irq(skb);
 
                priv->tx_skbuff[priv->skb_dirtytx] = NULL;
                priv->skb_dirtytx =
@@ -1057,6 +1056,54 @@ static const struct net_device_ops uhdlc_ops = {
        .ndo_tx_timeout = uhdlc_tx_timeout,
 };
 
+static int hdlc_map_iomem(char *name, int init_flag, void __iomem **ptr)
+{
+       struct device_node *np;
+       struct platform_device *pdev;
+       struct resource *res;
+       static int siram_init_flag;
+       int ret = 0;
+
+       np = of_find_compatible_node(NULL, NULL, name);
+       if (!np)
+               return -EINVAL;
+
+       pdev = of_find_device_by_node(np);
+       if (!pdev) {
+               pr_err("%pOFn: failed to lookup pdev\n", np);
+               of_node_put(np);
+               return -EINVAL;
+       }
+
+       of_node_put(np);
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       if (!res) {
+               ret = -EINVAL;
+               goto error_put_device;
+       }
+       *ptr = ioremap(res->start, resource_size(res));
+       if (!*ptr) {
+               ret = -ENOMEM;
+               goto error_put_device;
+       }
+
+       /* We've remapped the addresses, and we don't need the device any
+        * more, so we should release it.
+        */
+       put_device(&pdev->dev);
+
+       if (init_flag && siram_init_flag == 0) {
+               memset_io(*ptr, 0, resource_size(res));
+               siram_init_flag = 1;
+       }
+       return  0;
+
+error_put_device:
+       put_device(&pdev->dev);
+
+       return ret;
+}
+
 static int ucc_hdlc_probe(struct platform_device *pdev)
 {
        struct device_node *np = pdev->dev.of_node;
@@ -1151,6 +1198,15 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
                ret = ucc_of_parse_tdm(np, utdm, ut_info);
                if (ret)
                        goto free_utdm;
+
+               ret = hdlc_map_iomem("fsl,t1040-qe-si", 0,
+                                    (void __iomem **)&utdm->si_regs);
+               if (ret)
+                       goto free_utdm;
+               ret = hdlc_map_iomem("fsl,t1040-qe-siram", 1,
+                                    (void __iomem **)&utdm->siram);
+               if (ret)
+                       goto unmap_si_regs;
        }
 
        if (of_property_read_u16(np, "fsl,hmask", &uhdlc_priv->hmask))
@@ -1159,7 +1215,7 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
        ret = uhdlc_init(uhdlc_priv);
        if (ret) {
                dev_err(&pdev->dev, "Failed to init uhdlc\n");
-               goto free_utdm;
+               goto undo_uhdlc_init;
        }
 
        dev = alloc_hdlcdev(uhdlc_priv);
@@ -1188,6 +1244,9 @@ static int ucc_hdlc_probe(struct platform_device *pdev)
 free_dev:
        free_netdev(dev);
 undo_uhdlc_init:
+       iounmap(utdm->siram);
+unmap_si_regs:
+       iounmap(utdm->si_regs);
 free_utdm:
        if (uhdlc_priv->tsa)
                kfree(utdm);
index f6d3ecb..2a5668b 100644 (file)
@@ -1553,10 +1553,9 @@ ath10k_ce_alloc_dest_ring(struct ath10k *ar, unsigned int ce_id,
         * coherent DMA are unsupported
         */
        dest_ring->base_addr_owner_space_unaligned =
-               dma_zalloc_coherent(ar->dev,
-                                   (nentries * sizeof(struct ce_desc) +
-                                    CE_DESC_RING_ALIGN),
-                                   &base_addr, GFP_KERNEL);
+               dma_alloc_coherent(ar->dev,
+                                  (nentries * sizeof(struct ce_desc) + CE_DESC_RING_ALIGN),
+                                  &base_addr, GFP_KERNEL);
        if (!dest_ring->base_addr_owner_space_unaligned) {
                kfree(dest_ring);
                return ERR_PTR(-ENOMEM);
index 399b501..e8891f5 100644 (file)
@@ -548,7 +548,7 @@ static const struct ath10k_hw_params ath10k_hw_params_list[] = {
        {
                .id = WCN3990_HW_1_0_DEV_VERSION,
                .dev_id = 0,
-               .bus = ATH10K_BUS_PCI,
+               .bus = ATH10K_BUS_SNOC,
                .name = "wcn3990 hw1.0",
                .continuous_frag_desc = true,
                .tx_chain_mask = 0x7,
index e49b367..4975849 100644 (file)
@@ -5169,10 +5169,10 @@ static int ath10k_add_interface(struct ieee80211_hw *hw,
        if (vif->type == NL80211_IFTYPE_ADHOC ||
            vif->type == NL80211_IFTYPE_MESH_POINT ||
            vif->type == NL80211_IFTYPE_AP) {
-               arvif->beacon_buf = dma_zalloc_coherent(ar->dev,
-                                                       IEEE80211_MAX_FRAME_LEN,
-                                                       &arvif->beacon_paddr,
-                                                       GFP_ATOMIC);
+               arvif->beacon_buf = dma_alloc_coherent(ar->dev,
+                                                      IEEE80211_MAX_FRAME_LEN,
+                                                      &arvif->beacon_paddr,
+                                                      GFP_ATOMIC);
                if (!arvif->beacon_buf) {
                        ret = -ENOMEM;
                        ath10k_warn(ar, "failed to allocate beacon buffer: %d\n",
index 01b4edb..39e0b1c 100644 (file)
@@ -936,8 +936,7 @@ static int ath10k_pci_diag_read_mem(struct ath10k *ar, u32 address, void *data,
         */
        alloc_nbytes = min_t(unsigned int, nbytes, DIAG_TRANSFER_LIMIT);
 
-       data_buf = (unsigned char *)dma_zalloc_coherent(ar->dev,
-                                                      alloc_nbytes,
+       data_buf = (unsigned char *)dma_alloc_coherent(ar->dev, alloc_nbytes,
                                                       &ce_data_base,
                                                       GFP_ATOMIC);
 
index ba83740..8e236d1 100644 (file)
@@ -5193,7 +5193,7 @@ static int ath10k_wmi_alloc_chunk(struct ath10k *ar, u32 req_id,
        void *vaddr;
 
        pool_size = num_units * round_up(unit_len, 4);
-       vaddr = dma_zalloc_coherent(ar->dev, pool_size, &paddr, GFP_KERNEL);
+       vaddr = dma_alloc_coherent(ar->dev, pool_size, &paddr, GFP_KERNEL);
 
        if (!vaddr)
                return -ENOMEM;
index 5ab3e31..bab30f7 100644 (file)
@@ -174,9 +174,8 @@ static int wcn36xx_dxe_init_descs(struct device *dev, struct wcn36xx_dxe_ch *wcn
        int i;
 
        size = wcn_ch->desc_num * sizeof(struct wcn36xx_dxe_desc);
-       wcn_ch->cpu_addr = dma_zalloc_coherent(dev, size,
-                                              &wcn_ch->dma_addr,
-                                              GFP_KERNEL);
+       wcn_ch->cpu_addr = dma_alloc_coherent(dev, size, &wcn_ch->dma_addr,
+                                             GFP_KERNEL);
        if (!wcn_ch->cpu_addr)
                return -ENOMEM;
 
@@ -627,9 +626,9 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn)
                16 - (WCN36XX_BD_CHUNK_SIZE % 8);
 
        s = wcn->mgmt_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_H;
-       cpu_addr = dma_zalloc_coherent(wcn->dev, s,
-                                      &wcn->mgmt_mem_pool.phy_addr,
-                                      GFP_KERNEL);
+       cpu_addr = dma_alloc_coherent(wcn->dev, s,
+                                     &wcn->mgmt_mem_pool.phy_addr,
+                                     GFP_KERNEL);
        if (!cpu_addr)
                goto out_err;
 
@@ -642,9 +641,9 @@ int wcn36xx_dxe_allocate_mem_pools(struct wcn36xx *wcn)
                16 - (WCN36XX_BD_CHUNK_SIZE % 8);
 
        s = wcn->data_mem_pool.chunk_size * WCN36XX_DXE_CH_DESC_NUMB_TX_L;
-       cpu_addr = dma_zalloc_coherent(wcn->dev, s,
-                                      &wcn->data_mem_pool.phy_addr,
-                                      GFP_KERNEL);
+       cpu_addr = dma_alloc_coherent(wcn->dev, s,
+                                     &wcn->data_mem_pool.phy_addr,
+                                     GFP_KERNEL);
        if (!cpu_addr)
                goto out_err;
 
index 05a8348..3380aae 100644 (file)
@@ -99,7 +99,7 @@ static int wil_sring_alloc(struct wil6210_priv *wil,
        /* Status messages are allocated and initialized to 0. This is necessary
         * since DR bit should be initialized to 0.
         */
-       sring->va = dma_zalloc_coherent(dev, sz, &sring->pa, GFP_KERNEL);
+       sring->va = dma_alloc_coherent(dev, sz, &sring->pa, GFP_KERNEL);
        if (!sring->va)
                return -ENOMEM;
 
@@ -381,15 +381,15 @@ static int wil_ring_alloc_desc_ring(struct wil6210_priv *wil,
        if (!ring->ctx)
                goto err;
 
-       ring->va = dma_zalloc_coherent(dev, sz, &ring->pa, GFP_KERNEL);
+       ring->va = dma_alloc_coherent(dev, sz, &ring->pa, GFP_KERNEL);
        if (!ring->va)
                goto err_free_ctx;
 
        if (ring->is_rx) {
                sz = sizeof(*ring->edma_rx_swtail.va);
                ring->edma_rx_swtail.va =
-                       dma_zalloc_coherent(dev, sz, &ring->edma_rx_swtail.pa,
-                                           GFP_KERNEL);
+                       dma_alloc_coherent(dev, sz, &ring->edma_rx_swtail.pa,
+                                          GFP_KERNEL);
                if (!ring->edma_rx_swtail.va)
                        goto err_free_va;
        }
index dfc4c34..b34e519 100644 (file)
@@ -431,9 +431,9 @@ static int alloc_ringmemory(struct b43_dmaring *ring)
        u16 ring_mem_size = (ring->type == B43_DMA_64BIT) ?
                                B43_DMA64_RINGMEMSIZE : B43_DMA32_RINGMEMSIZE;
 
-       ring->descbase = dma_zalloc_coherent(ring->dev->dev->dma_dev,
-                                            ring_mem_size, &(ring->dmabase),
-                                            GFP_KERNEL);
+       ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
+                                           ring_mem_size, &(ring->dmabase),
+                                           GFP_KERNEL);
        if (!ring->descbase)
                return -ENOMEM;
 
index 1b1da7d..2ce1537 100644 (file)
@@ -331,9 +331,9 @@ void free_descriptor_buffer(struct b43legacy_dmaring *ring,
 static int alloc_ringmemory(struct b43legacy_dmaring *ring)
 {
        /* GFP flags must match the flags in free_ringmemory()! */
-       ring->descbase = dma_zalloc_coherent(ring->dev->dev->dma_dev,
-                                            B43legacy_DMA_RINGMEMSIZE,
-                                            &(ring->dmabase), GFP_KERNEL);
+       ring->descbase = dma_alloc_coherent(ring->dev->dev->dma_dev,
+                                           B43legacy_DMA_RINGMEMSIZE,
+                                           &(ring->dmabase), GFP_KERNEL);
        if (!ring->descbase)
                return -ENOMEM;
 
index 16d7dda..0f69b3f 100644 (file)
@@ -1281,10 +1281,10 @@ static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
        u32 addr;
 
        devinfo->shared.scratch =
-               dma_zalloc_coherent(&devinfo->pdev->dev,
-                                       BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
-                                       &devinfo->shared.scratch_dmahandle,
-                                       GFP_KERNEL);
+               dma_alloc_coherent(&devinfo->pdev->dev,
+                                  BRCMF_DMA_D2H_SCRATCH_BUF_LEN,
+                                  &devinfo->shared.scratch_dmahandle,
+                                  GFP_KERNEL);
        if (!devinfo->shared.scratch)
                goto fail;
 
@@ -1298,10 +1298,10 @@ static int brcmf_pcie_init_scratchbuffers(struct brcmf_pciedev_info *devinfo)
        brcmf_pcie_write_tcm32(devinfo, addr, BRCMF_DMA_D2H_SCRATCH_BUF_LEN);
 
        devinfo->shared.ringupd =
-               dma_zalloc_coherent(&devinfo->pdev->dev,
-                                       BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
-                                       &devinfo->shared.ringupd_dmahandle,
-                                       GFP_KERNEL);
+               dma_alloc_coherent(&devinfo->pdev->dev,
+                                  BRCMF_DMA_D2H_RINGUPD_BUF_LEN,
+                                  &devinfo->shared.ringupd_dmahandle,
+                                  GFP_KERNEL);
        if (!devinfo->shared.ringupd)
                goto fail;
 
index 491ca3c..83d5bce 100644 (file)
@@ -1,6 +1,6 @@
 config IWLWIFI
        tristate "Intel Wireless WiFi Next Gen AGN - Wireless-N/Advanced-N/Ultimate-N (iwlwifi) "
-       depends on PCI && HAS_IOMEM
+       depends on PCI && HAS_IOMEM && CFG80211
        select FW_LOADER
        ---help---
          Select to build the driver supporting the:
@@ -47,6 +47,7 @@ if IWLWIFI
 config IWLWIFI_LEDS
        bool
        depends on LEDS_CLASS=y || LEDS_CLASS=IWLWIFI
+       depends on IWLMVM || IWLDVM
        select LEDS_TRIGGERS
        select MAC80211_LEDS
        default y
index e965cc5..9e850c2 100644 (file)
@@ -711,30 +711,24 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
         * Allocate the circular buffer of Read Buffer Descriptors
         * (RBDs)
         */
-       rxq->bd = dma_zalloc_coherent(dev,
-                                     free_size * rxq->queue_size,
-                                     &rxq->bd_dma, GFP_KERNEL);
+       rxq->bd = dma_alloc_coherent(dev, free_size * rxq->queue_size,
+                                    &rxq->bd_dma, GFP_KERNEL);
        if (!rxq->bd)
                goto err;
 
        if (trans->cfg->mq_rx_supported) {
-               rxq->used_bd = dma_zalloc_coherent(dev,
-                                                  (use_rx_td ?
-                                                  sizeof(*rxq->cd) :
-                                                  sizeof(__le32)) *
-                                                  rxq->queue_size,
-                                                  &rxq->used_bd_dma,
-                                                  GFP_KERNEL);
+               rxq->used_bd = dma_alloc_coherent(dev,
+                                                 (use_rx_td ? sizeof(*rxq->cd) : sizeof(__le32)) * rxq->queue_size,
+                                                 &rxq->used_bd_dma,
+                                                 GFP_KERNEL);
                if (!rxq->used_bd)
                        goto err;
        }
 
        /* Allocate the driver's pointer to receive buffer status */
-       rxq->rb_stts = dma_zalloc_coherent(dev, use_rx_td ?
-                                          sizeof(__le16) :
-                                          sizeof(struct iwl_rb_status),
-                                          &rxq->rb_stts_dma,
-                                          GFP_KERNEL);
+       rxq->rb_stts = dma_alloc_coherent(dev,
+                                         use_rx_td ? sizeof(__le16) : sizeof(struct iwl_rb_status),
+                                         &rxq->rb_stts_dma, GFP_KERNEL);
        if (!rxq->rb_stts)
                goto err;
 
@@ -742,16 +736,14 @@ static int iwl_pcie_alloc_rxq_dma(struct iwl_trans *trans,
                return 0;
 
        /* Allocate the driver's pointer to TR tail */
-       rxq->tr_tail = dma_zalloc_coherent(dev, sizeof(__le16),
-                                          &rxq->tr_tail_dma,
-                                          GFP_KERNEL);
+       rxq->tr_tail = dma_alloc_coherent(dev, sizeof(__le16),
+                                         &rxq->tr_tail_dma, GFP_KERNEL);
        if (!rxq->tr_tail)
                goto err;
 
        /* Allocate the driver's pointer to CR tail */
-       rxq->cr_tail = dma_zalloc_coherent(dev, sizeof(__le16),
-                                          &rxq->cr_tail_dma,
-                                          GFP_KERNEL);
+       rxq->cr_tail = dma_alloc_coherent(dev, sizeof(__le16),
+                                         &rxq->cr_tail_dma, GFP_KERNEL);
        if (!rxq->cr_tail)
                goto err;
        /*
@@ -1947,9 +1939,8 @@ int iwl_pcie_alloc_ict(struct iwl_trans *trans)
        struct iwl_trans_pcie *trans_pcie = IWL_TRANS_GET_PCIE_TRANS(trans);
 
        trans_pcie->ict_tbl =
-               dma_zalloc_coherent(trans->dev, ICT_SIZE,
-                                  &trans_pcie->ict_tbl_dma,
-                                  GFP_KERNEL);
+               dma_alloc_coherent(trans->dev, ICT_SIZE,
+                                  &trans_pcie->ict_tbl_dma, GFP_KERNEL);
        if (!trans_pcie->ict_tbl)
                return -ENOMEM;
 
index 3a4b878..6359053 100644 (file)
@@ -2761,6 +2761,11 @@ static int mac80211_hwsim_new_radio(struct genl_info *info,
                                        BIT(NL80211_CHAN_WIDTH_160);
        }
 
+       if (!n_limits) {
+               err = -EINVAL;
+               goto failed_hw;
+       }
+
        data->if_combination.n_limits = n_limits;
        data->if_combination.max_interfaces = 2048;
        data->if_combination.limits = data->if_limits;
@@ -3549,7 +3554,7 @@ static int hwsim_get_radio_nl(struct sk_buff *msg, struct genl_info *info)
                        goto out_err;
                }
 
-               genlmsg_reply(skb, info);
+               res = genlmsg_reply(skb, info);
                break;
        }
 
index 497e762..b2cabce 100644 (file)
@@ -212,24 +212,24 @@ void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev)
        mt76x02_add_rate_power_offset(t, delta);
 }
 
-void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
+void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp)
 {
        struct mt76x0_chan_map {
                u8 chan;
                u8 offset;
        } chan_map[] = {
-               {   2,  0 }, {   4,  1 }, {   6,  2 }, {   8,  3 },
-               {  10,  4 }, {  12,  5 }, {  14,  6 }, {  38,  0 },
-               {  44,  1 }, {  48,  2 }, {  54,  3 }, {  60,  4 },
-               {  64,  5 }, { 102,  6 }, { 108,  7 }, { 112,  8 },
-               { 118,  9 }, { 124, 10 }, { 128, 11 }, { 134, 12 },
-               { 140, 13 }, { 151, 14 }, { 157, 15 }, { 161, 16 },
-               { 167, 17 }, { 171, 18 }, { 173, 19 },
+               {   2,  0 }, {   4,  2 }, {   6,  4 }, {   8,  6 },
+               {  10,  8 }, {  12, 10 }, {  14, 12 }, {  38,  0 },
+               {  44,  2 }, {  48,  4 }, {  54,  6 }, {  60,  8 },
+               {  64, 10 }, { 102, 12 }, { 108, 14 }, { 112, 16 },
+               { 118, 18 }, { 124, 20 }, { 128, 22 }, { 134, 24 },
+               { 140, 26 }, { 151, 28 }, { 157, 30 }, { 161, 32 },
+               { 167, 34 }, { 171, 36 }, { 175, 38 },
        };
        struct ieee80211_channel *chan = dev->mt76.chandef.chan;
        u8 offset, addr;
+       int i, idx = 0;
        u16 data;
-       int i;
 
        if (mt76x0_tssi_enabled(dev)) {
                s8 target_power;
@@ -239,14 +239,14 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
                else
                        data = mt76x02_eeprom_get(dev, MT_EE_2G_TARGET_POWER);
                target_power = (data & 0xff) - dev->mt76.rate_power.ofdm[7];
-               info[0] = target_power + mt76x0_get_delta(dev);
-               info[1] = 0;
+               *tp = target_power + mt76x0_get_delta(dev);
 
                return;
        }
 
        for (i = 0; i < ARRAY_SIZE(chan_map); i++) {
-               if (chan_map[i].chan <= chan->hw_value) {
+               if (chan->hw_value <= chan_map[i].chan) {
+                       idx = (chan->hw_value == chan_map[i].chan);
                        offset = chan_map[i].offset;
                        break;
                }
@@ -258,13 +258,16 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
                addr = MT_EE_TX_POWER_DELTA_BW80 + offset;
        } else {
                switch (chan->hw_value) {
+               case 42:
+                       offset = 2;
+                       break;
                case 58:
                        offset = 8;
                        break;
                case 106:
                        offset = 14;
                        break;
-               case 112:
+               case 122:
                        offset = 20;
                        break;
                case 155:
@@ -277,14 +280,9 @@ void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info)
        }
 
        data = mt76x02_eeprom_get(dev, addr);
-
-       info[0] = data;
-       if (!info[0] || info[0] > 0x3f)
-               info[0] = 5;
-
-       info[1] = data >> 8;
-       if (!info[1] || info[1] > 0x3f)
-               info[1] = 5;
+       *tp = data >> (8 * idx);
+       if (*tp < 0 || *tp > 0x3f)
+               *tp = 5;
 }
 
 static int mt76x0_check_eeprom(struct mt76x02_dev *dev)
index ee9ade9..42b259f 100644 (file)
@@ -26,7 +26,7 @@ struct mt76x02_dev;
 int mt76x0_eeprom_init(struct mt76x02_dev *dev);
 void mt76x0_read_rx_gain(struct mt76x02_dev *dev);
 void mt76x0_get_tx_power_per_rate(struct mt76x02_dev *dev);
-void mt76x0_get_power_info(struct mt76x02_dev *dev, u8 *info);
+void mt76x0_get_power_info(struct mt76x02_dev *dev, s8 *tp);
 
 static inline s8 s6_to_s8(u32 val)
 {
index 1eb1a80..b616670 100644 (file)
@@ -845,17 +845,17 @@ static void mt76x0_phy_tssi_calibrate(struct mt76x02_dev *dev)
 void mt76x0_phy_set_txpower(struct mt76x02_dev *dev)
 {
        struct mt76_rate_power *t = &dev->mt76.rate_power;
-       u8 info[2];
+       s8 info;
 
        mt76x0_get_tx_power_per_rate(dev);
-       mt76x0_get_power_info(dev, info);
+       mt76x0_get_power_info(dev, &info);
 
-       mt76x02_add_rate_power_offset(t, info[0]);
+       mt76x02_add_rate_power_offset(t, info);
        mt76x02_limit_rate_power(t, dev->mt76.txpower_conf);
        dev->mt76.txpower_cur = mt76x02_get_max_rate_power(t);
-       mt76x02_add_rate_power_offset(t, -info[0]);
+       mt76x02_add_rate_power_offset(t, -info);
 
-       mt76x02_phy_set_txpower(dev, info[0], info[1]);
+       mt76x02_phy_set_txpower(dev, info, info);
 }
 
 void mt76x0_phy_calibrate(struct mt76x02_dev *dev, bool power_on)
index 0e6b43b..a5ea3ba 100644 (file)
@@ -158,39 +158,49 @@ static const struct ieee80211_ops mt76x0u_ops = {
        .get_txpower = mt76x02_get_txpower,
 };
 
-static int mt76x0u_register_device(struct mt76x02_dev *dev)
+static int mt76x0u_init_hardware(struct mt76x02_dev *dev)
 {
-       struct ieee80211_hw *hw = dev->mt76.hw;
        int err;
 
-       err = mt76u_alloc_queues(&dev->mt76);
-       if (err < 0)
-               goto out_err;
-
-       err = mt76u_mcu_init_rx(&dev->mt76);
-       if (err < 0)
-               goto out_err;
-
        mt76x0_chip_onoff(dev, true, true);
-       if (!mt76x02_wait_for_mac(&dev->mt76)) {
-               err = -ETIMEDOUT;
-               goto out_err;
-       }
+
+       if (!mt76x02_wait_for_mac(&dev->mt76))
+               return -ETIMEDOUT;
 
        err = mt76x0u_mcu_init(dev);
        if (err < 0)
-               goto out_err;
+               return err;
 
        mt76x0_init_usb_dma(dev);
        err = mt76x0_init_hardware(dev);
        if (err < 0)
-               goto out_err;
+               return err;
 
        mt76_rmw(dev, MT_US_CYC_CFG, MT_US_CYC_CNT, 0x1e);
        mt76_wr(dev, MT_TXOP_CTRL_CFG,
                FIELD_PREP(MT_TXOP_TRUN_EN, 0x3f) |
                FIELD_PREP(MT_TXOP_EXT_CCA_DLY, 0x58));
 
+       return 0;
+}
+
+static int mt76x0u_register_device(struct mt76x02_dev *dev)
+{
+       struct ieee80211_hw *hw = dev->mt76.hw;
+       int err;
+
+       err = mt76u_alloc_queues(&dev->mt76);
+       if (err < 0)
+               goto out_err;
+
+       err = mt76u_mcu_init_rx(&dev->mt76);
+       if (err < 0)
+               goto out_err;
+
+       err = mt76x0u_init_hardware(dev);
+       if (err < 0)
+               goto out_err;
+
        err = mt76x0_register_device(dev);
        if (err < 0)
                goto out_err;
@@ -301,6 +311,8 @@ static int __maybe_unused mt76x0_suspend(struct usb_interface *usb_intf,
 
        mt76u_stop_queues(&dev->mt76);
        mt76x0u_mac_stop(dev);
+       clear_bit(MT76_STATE_MCU_RUNNING, &dev->mt76.state);
+       mt76x0_chip_onoff(dev, false, false);
        usb_kill_urb(usb->mcu.res.urb);
 
        return 0;
@@ -328,7 +340,7 @@ static int __maybe_unused mt76x0_resume(struct usb_interface *usb_intf)
        tasklet_enable(&usb->rx_tasklet);
        tasklet_enable(&usb->tx_tasklet);
 
-       ret = mt76x0_init_hardware(dev);
+       ret = mt76x0u_init_hardware(dev);
        if (ret)
                goto err;
 
index 528cb04..4956a54 100644 (file)
@@ -119,9 +119,9 @@ static int rt2x00mmio_alloc_queue_dma(struct rt2x00_dev *rt2x00dev,
        /*
         * Allocate DMA memory for descriptor and buffer.
         */
-       addr = dma_zalloc_coherent(rt2x00dev->dev,
-                                  queue->limit * queue->desc_size, &dma,
-                                  GFP_KERNEL);
+       addr = dma_alloc_coherent(rt2x00dev->dev,
+                                 queue->limit * queue->desc_size, &dma,
+                                 GFP_KERNEL);
        if (!addr)
                return -ENOMEM;
 
index bd10165..4d4b077 100644 (file)
@@ -164,6 +164,12 @@ static int wl12xx_sdio_power_on(struct wl12xx_sdio_glue *glue)
        }
 
        sdio_claim_host(func);
+       /*
+        * To guarantee that the SDIO card is power cycled, as required to make
+        * the FW programming to succeed, let's do a brute force HW reset.
+        */
+       mmc_hw_reset(card->host);
+
        sdio_enable_func(func);
        sdio_release_host(func);
 
@@ -174,20 +180,13 @@ static int wl12xx_sdio_power_off(struct wl12xx_sdio_glue *glue)
 {
        struct sdio_func *func = dev_to_sdio_func(glue->dev);
        struct mmc_card *card = func->card;
-       int error;
 
        sdio_claim_host(func);
        sdio_disable_func(func);
        sdio_release_host(func);
 
        /* Let runtime PM know the card is powered off */
-       error = pm_runtime_put(&card->dev);
-       if (error < 0 && error != -EBUSY) {
-               dev_err(&card->dev, "%s failed: %i\n", __func__, error);
-
-               return error;
-       }
-
+       pm_runtime_put(&card->dev);
        return 0;
 }
 
index 64b2186..3a93e4d 100644 (file)
@@ -530,8 +530,10 @@ static int virt_wifi_newlink(struct net *src_net, struct net_device *dev,
        SET_NETDEV_DEV(dev, &priv->lowerdev->dev);
        dev->ieee80211_ptr = kzalloc(sizeof(*dev->ieee80211_ptr), GFP_KERNEL);
 
-       if (!dev->ieee80211_ptr)
+       if (!dev->ieee80211_ptr) {
+               err = -ENOMEM;
                goto remove_handler;
+       }
 
        dev->ieee80211_ptr->iftype = NL80211_IFTYPE_STATION;
        dev->ieee80211_ptr->wiphy = common_wiphy;
index 5ee5f40..f1eaa3c 100644 (file)
@@ -1339,10 +1339,10 @@ static int switchtec_ntb_init_shared_mw(struct switchtec_ntb *sndev)
        int rc;
 
        sndev->nr_rsvd_luts++;
-       sndev->self_shared = dma_zalloc_coherent(&sndev->stdev->pdev->dev,
-                                                LUT_SIZE,
-                                                &sndev->self_shared_dma,
-                                                GFP_KERNEL);
+       sndev->self_shared = dma_alloc_coherent(&sndev->stdev->pdev->dev,
+                                               LUT_SIZE,
+                                               &sndev->self_shared_dma,
+                                               GFP_KERNEL);
        if (!sndev->self_shared) {
                dev_err(&sndev->stdev->dev,
                        "unable to allocate memory for shared mw\n");
index 0cf58ca..3cf5027 100644 (file)
@@ -26,6 +26,12 @@ static int nvdimm_probe(struct device *dev)
        struct nvdimm_drvdata *ndd;
        int rc;
 
+       rc = nvdimm_security_setup_events(dev);
+       if (rc < 0) {
+               dev_err(dev, "security event setup failed: %d\n", rc);
+               return rc;
+       }
+
        rc = nvdimm_check_config_data(dev);
        if (rc) {
                /* not required for non-aliased nvdimm, ex. NVDIMM-N */
index 4890310..efe412a 100644 (file)
@@ -578,13 +578,25 @@ struct nvdimm *__nvdimm_create(struct nvdimm_bus *nvdimm_bus,
 }
 EXPORT_SYMBOL_GPL(__nvdimm_create);
 
-int nvdimm_security_setup_events(struct nvdimm *nvdimm)
+static void shutdown_security_notify(void *data)
 {
-       nvdimm->sec.overwrite_state = sysfs_get_dirent(nvdimm->dev.kobj.sd,
-                       "security");
+       struct nvdimm *nvdimm = data;
+
+       sysfs_put(nvdimm->sec.overwrite_state);
+}
+
+int nvdimm_security_setup_events(struct device *dev)
+{
+       struct nvdimm *nvdimm = to_nvdimm(dev);
+
+       if (nvdimm->sec.state < 0 || !nvdimm->sec.ops
+                       || !nvdimm->sec.ops->overwrite)
+               return 0;
+       nvdimm->sec.overwrite_state = sysfs_get_dirent(dev->kobj.sd, "security");
        if (!nvdimm->sec.overwrite_state)
-               return -ENODEV;
-       return 0;
+               return -ENOMEM;
+
+       return devm_add_action_or_reset(dev, shutdown_security_notify, nvdimm);
 }
 EXPORT_SYMBOL_GPL(nvdimm_security_setup_events);
 
index 2b2cf4e..e5ffd57 100644 (file)
@@ -54,12 +54,12 @@ struct nvdimm {
 };
 
 static inline enum nvdimm_security_state nvdimm_security_state(
-               struct nvdimm *nvdimm, bool master)
+               struct nvdimm *nvdimm, enum nvdimm_passphrase_type ptype)
 {
        if (!nvdimm->sec.ops)
                return -ENXIO;
 
-       return nvdimm->sec.ops->state(nvdimm, master);
+       return nvdimm->sec.ops->state(nvdimm, ptype);
 }
 int nvdimm_security_freeze(struct nvdimm *nvdimm);
 #if IS_ENABLED(CONFIG_NVDIMM_KEYS)
index cfde992..379bf43 100644 (file)
@@ -250,6 +250,7 @@ long nvdimm_clear_poison(struct device *dev, phys_addr_t phys,
 void nvdimm_set_aliasing(struct device *dev);
 void nvdimm_set_locked(struct device *dev);
 void nvdimm_clear_locked(struct device *dev);
+int nvdimm_security_setup_events(struct device *dev);
 #if IS_ENABLED(CONFIG_NVDIMM_KEYS)
 int nvdimm_security_unlock(struct device *dev);
 #else
index 08f2c92..6a9dd68 100644 (file)
@@ -1253,6 +1253,7 @@ static u32 nvme_passthru_start(struct nvme_ctrl *ctrl, struct nvme_ns *ns,
         * effects say only one namespace is affected.
         */
        if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
+               mutex_lock(&ctrl->scan_lock);
                nvme_start_freeze(ctrl);
                nvme_wait_freeze(ctrl);
        }
@@ -1281,8 +1282,10 @@ static void nvme_passthru_end(struct nvme_ctrl *ctrl, u32 effects)
         */
        if (effects & NVME_CMD_EFFECTS_LBCC)
                nvme_update_formats(ctrl);
-       if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK))
+       if (effects & (NVME_CMD_EFFECTS_LBCC | NVME_CMD_EFFECTS_CSE_MASK)) {
                nvme_unfreeze(ctrl);
+               mutex_unlock(&ctrl->scan_lock);
+       }
        if (effects & NVME_CMD_EFFECTS_CCC)
                nvme_init_identify(ctrl);
        if (effects & (NVME_CMD_EFFECTS_NIC | NVME_CMD_EFFECTS_NCC))
@@ -2173,18 +2176,20 @@ static void nvme_init_subnqn(struct nvme_subsystem *subsys, struct nvme_ctrl *ct
        size_t nqnlen;
        int off;
 
-       nqnlen = strnlen(id->subnqn, NVMF_NQN_SIZE);
-       if (nqnlen > 0 && nqnlen < NVMF_NQN_SIZE) {
-               strlcpy(subsys->subnqn, id->subnqn, NVMF_NQN_SIZE);
-               return;
-       }
+       if(!(ctrl->quirks & NVME_QUIRK_IGNORE_DEV_SUBNQN)) {
+               nqnlen = strnlen(id->subnqn, NVMF_NQN_SIZE);
+               if (nqnlen > 0 && nqnlen < NVMF_NQN_SIZE) {
+                       strlcpy(subsys->subnqn, id->subnqn, NVMF_NQN_SIZE);
+                       return;
+               }
 
-       if (ctrl->vs >= NVME_VS(1, 2, 1))
-               dev_warn(ctrl->device, "missing or invalid SUBNQN field.\n");
+               if (ctrl->vs >= NVME_VS(1, 2, 1))
+                       dev_warn(ctrl->device, "missing or invalid SUBNQN field.\n");
+       }
 
        /* Generate a "fake" NQN per Figure 254 in NVMe 1.3 + ECN 001 */
        off = snprintf(subsys->subnqn, NVMF_NQN_SIZE,
-                       "nqn.2014.08.org.nvmexpress:%4x%4x",
+                       "nqn.2014.08.org.nvmexpress:%04x%04x",
                        le16_to_cpu(id->vid), le16_to_cpu(id->ssvid));
        memcpy(subsys->subnqn + off, id->sn, sizeof(id->sn));
        off += sizeof(id->sn);
@@ -2500,7 +2505,6 @@ int nvme_init_identify(struct nvme_ctrl *ctrl)
        ctrl->oaes = le32_to_cpu(id->oaes);
        atomic_set(&ctrl->abort_limit, id->acl + 1);
        ctrl->vwc = id->vwc;
-       ctrl->cntlid = le16_to_cpup(&id->cntlid);
        if (id->mdts)
                max_hw_sectors = 1 << (id->mdts + page_shift - 9);
        else
@@ -3400,6 +3404,7 @@ static void nvme_scan_work(struct work_struct *work)
        if (nvme_identify_ctrl(ctrl, &id))
                return;
 
+       mutex_lock(&ctrl->scan_lock);
        nn = le32_to_cpu(id->nn);
        if (ctrl->vs >= NVME_VS(1, 1, 0) &&
            !(ctrl->quirks & NVME_QUIRK_IDENTIFY_CNS)) {
@@ -3408,6 +3413,7 @@ static void nvme_scan_work(struct work_struct *work)
        }
        nvme_scan_ns_sequential(ctrl, nn);
 out_free_id:
+       mutex_unlock(&ctrl->scan_lock);
        kfree(id);
        down_write(&ctrl->namespaces_rwsem);
        list_sort(NULL, &ctrl->namespaces, ns_cmp);
@@ -3651,6 +3657,7 @@ int nvme_init_ctrl(struct nvme_ctrl *ctrl, struct device *dev,
 
        ctrl->state = NVME_CTRL_NEW;
        spin_lock_init(&ctrl->lock);
+       mutex_init(&ctrl->scan_lock);
        INIT_LIST_HEAD(&ctrl->namespaces);
        init_rwsem(&ctrl->namespaces_rwsem);
        ctrl->dev = dev;
index b2ab213..3eb908c 100644 (file)
@@ -874,6 +874,8 @@ static int nvmf_parse_options(struct nvmf_ctrl_options *opts,
        if (opts->discovery_nqn) {
                opts->kato = 0;
                opts->nr_io_queues = 0;
+               opts->nr_write_queues = 0;
+               opts->nr_poll_queues = 0;
                opts->duplicate_connect = true;
        }
        if (ctrl_loss_tmo < 0)
index 183ec17..b9fff3b 100644 (file)
@@ -545,8 +545,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
        timer_setup(&ctrl->anatt_timer, nvme_anatt_timeout, 0);
        ctrl->ana_log_size = sizeof(struct nvme_ana_rsp_hdr) +
                ctrl->nanagrpid * sizeof(struct nvme_ana_group_desc);
-       if (!(ctrl->anacap & (1 << 6)))
-               ctrl->ana_log_size += ctrl->max_namespaces * sizeof(__le32);
+       ctrl->ana_log_size += ctrl->max_namespaces * sizeof(__le32);
 
        if (ctrl->ana_log_size > ctrl->max_hw_sectors << SECTOR_SHIFT) {
                dev_err(ctrl->device,
@@ -570,6 +569,7 @@ int nvme_mpath_init(struct nvme_ctrl *ctrl, struct nvme_id_ctrl *id)
        return 0;
 out_free_ana_log_buf:
        kfree(ctrl->ana_log_buf);
+       ctrl->ana_log_buf = NULL;
 out:
        return error;
 }
@@ -577,5 +577,6 @@ out:
 void nvme_mpath_uninit(struct nvme_ctrl *ctrl)
 {
        kfree(ctrl->ana_log_buf);
+       ctrl->ana_log_buf = NULL;
 }
 
index 2b36ac9..c4a1bb4 100644 (file)
@@ -90,6 +90,11 @@ enum nvme_quirks {
         * Set MEDIUM priority on SQ creation
         */
        NVME_QUIRK_MEDIUM_PRIO_SQ               = (1 << 7),
+
+       /*
+        * Ignore device provided subnqn.
+        */
+       NVME_QUIRK_IGNORE_DEV_SUBNQN            = (1 << 8),
 };
 
 /*
@@ -149,6 +154,7 @@ struct nvme_ctrl {
        enum nvme_ctrl_state state;
        bool identified;
        spinlock_t lock;
+       struct mutex scan_lock;
        const struct nvme_ctrl_ops *ops;
        struct request_queue *admin_q;
        struct request_queue *connect_q;
index 5a0bf6a..7fee665 100644 (file)
@@ -95,6 +95,7 @@ struct nvme_dev;
 struct nvme_queue;
 
 static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown);
+static bool __nvme_disable_io_queues(struct nvme_dev *dev, u8 opcode);
 
 /*
  * Represents an NVM Express device.  Each nvme_dev is a PCI function.
@@ -1019,9 +1020,11 @@ static void nvme_complete_cqes(struct nvme_queue *nvmeq, u16 start, u16 end)
 
 static inline void nvme_update_cq_head(struct nvme_queue *nvmeq)
 {
-       if (++nvmeq->cq_head == nvmeq->q_depth) {
+       if (nvmeq->cq_head == nvmeq->q_depth - 1) {
                nvmeq->cq_head = 0;
                nvmeq->cq_phase = !nvmeq->cq_phase;
+       } else {
+               nvmeq->cq_head++;
        }
 }
 
@@ -1420,6 +1423,14 @@ static int nvme_suspend_queue(struct nvme_queue *nvmeq)
        return 0;
 }
 
+static void nvme_suspend_io_queues(struct nvme_dev *dev)
+{
+       int i;
+
+       for (i = dev->ctrl.queue_count - 1; i > 0; i--)
+               nvme_suspend_queue(&dev->queues[i]);
+}
+
 static void nvme_disable_admin_queue(struct nvme_dev *dev, bool shutdown)
 {
        struct nvme_queue *nvmeq = &dev->queues[0];
@@ -1485,8 +1496,8 @@ static int nvme_alloc_queue(struct nvme_dev *dev, int qid, int depth)
        if (dev->ctrl.queue_count > qid)
                return 0;
 
-       nvmeq->cqes = dma_zalloc_coherent(dev->dev, CQ_SIZE(depth),
-                                         &nvmeq->cq_dma_addr, GFP_KERNEL);
+       nvmeq->cqes = dma_alloc_coherent(dev->dev, CQ_SIZE(depth),
+                                        &nvmeq->cq_dma_addr, GFP_KERNEL);
        if (!nvmeq->cqes)
                goto free_nvmeq;
 
@@ -1885,8 +1896,9 @@ static void nvme_free_host_mem(struct nvme_dev *dev)
                struct nvme_host_mem_buf_desc *desc = &dev->host_mem_descs[i];
                size_t size = le32_to_cpu(desc->size) * dev->ctrl.page_size;
 
-               dma_free_coherent(dev->dev, size, dev->host_mem_desc_bufs[i],
-                               le64_to_cpu(desc->addr));
+               dma_free_attrs(dev->dev, size, dev->host_mem_desc_bufs[i],
+                              le64_to_cpu(desc->addr),
+                              DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN);
        }
 
        kfree(dev->host_mem_desc_bufs);
@@ -1915,8 +1927,8 @@ static int __nvme_alloc_host_mem(struct nvme_dev *dev, u64 preferred,
        if (dev->ctrl.hmmaxd && dev->ctrl.hmmaxd < max_entries)
                max_entries = dev->ctrl.hmmaxd;
 
-       descs = dma_zalloc_coherent(dev->dev, max_entries * sizeof(*descs),
-                       &descs_dma, GFP_KERNEL);
+       descs = dma_alloc_coherent(dev->dev, max_entries * sizeof(*descs),
+                                  &descs_dma, GFP_KERNEL);
        if (!descs)
                goto out;
 
@@ -1952,8 +1964,9 @@ out_free_bufs:
        while (--i >= 0) {
                size_t size = le32_to_cpu(descs[i].size) * dev->ctrl.page_size;
 
-               dma_free_coherent(dev->dev, size, bufs[i],
-                               le64_to_cpu(descs[i].addr));
+               dma_free_attrs(dev->dev, size, bufs[i],
+                              le64_to_cpu(descs[i].addr),
+                              DMA_ATTR_NO_KERNEL_MAPPING | DMA_ATTR_NO_WARN);
        }
 
        kfree(bufs);
@@ -2028,14 +2041,18 @@ static int nvme_setup_host_mem(struct nvme_dev *dev)
        return ret;
 }
 
+/* irq_queues covers admin queue */
 static void nvme_calc_io_queues(struct nvme_dev *dev, unsigned int irq_queues)
 {
        unsigned int this_w_queues = write_queues;
 
+       WARN_ON(!irq_queues);
+
        /*
-        * Setup read/write queue split
+        * Setup read/write queue split, assign admin queue one independent
+        * irq vector if irq_queues is > 1.
         */
-       if (irq_queues == 1) {
+       if (irq_queues <= 2) {
                dev->io_queues[HCTX_TYPE_DEFAULT] = 1;
                dev->io_queues[HCTX_TYPE_READ] = 0;
                return;
@@ -2043,21 +2060,21 @@ static void nvme_calc_io_queues(struct nvme_dev *dev, unsigned int irq_queues)
 
        /*
         * If 'write_queues' is set, ensure it leaves room for at least
-        * one read queue
+        * one read queue and one admin queue
         */
        if (this_w_queues >= irq_queues)
-               this_w_queues = irq_queues - 1;
+               this_w_queues = irq_queues - 2;
 
        /*
         * If 'write_queues' is set to zero, reads and writes will share
         * a queue set.
         */
        if (!this_w_queues) {
-               dev->io_queues[HCTX_TYPE_DEFAULT] = irq_queues;
+               dev->io_queues[HCTX_TYPE_DEFAULT] = irq_queues - 1;
                dev->io_queues[HCTX_TYPE_READ] = 0;
        } else {
                dev->io_queues[HCTX_TYPE_DEFAULT] = this_w_queues;
-               dev->io_queues[HCTX_TYPE_READ] = irq_queues - this_w_queues;
+               dev->io_queues[HCTX_TYPE_READ] = irq_queues - this_w_queues - 1;
        }
 }
 
@@ -2082,7 +2099,7 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
                this_p_queues = nr_io_queues - 1;
                irq_queues = 1;
        } else {
-               irq_queues = nr_io_queues - this_p_queues;
+               irq_queues = nr_io_queues - this_p_queues + 1;
        }
        dev->io_queues[HCTX_TYPE_POLL] = this_p_queues;
 
@@ -2102,8 +2119,9 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
                 * If we got a failure and we're down to asking for just
                 * 1 + 1 queues, just ask for a single vector. We'll share
                 * that between the single IO queue and the admin queue.
+                * Otherwise, we assign one independent vector to admin queue.
                 */
-               if (result >= 0 && irq_queues > 1)
+               if (irq_queues > 1)
                        irq_queues = irq_sets[0] + irq_sets[1] + 1;
 
                result = pci_alloc_irq_vectors_affinity(pdev, irq_queues,
@@ -2132,6 +2150,12 @@ static int nvme_setup_irqs(struct nvme_dev *dev, unsigned int nr_io_queues)
        return result;
 }
 
+static void nvme_disable_io_queues(struct nvme_dev *dev)
+{
+       if (__nvme_disable_io_queues(dev, nvme_admin_delete_sq))
+               __nvme_disable_io_queues(dev, nvme_admin_delete_cq);
+}
+
 static int nvme_setup_io_queues(struct nvme_dev *dev)
 {
        struct nvme_queue *adminq = &dev->queues[0];
@@ -2168,6 +2192,7 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        } while (1);
        adminq->q_db = dev->dbs;
 
+ retry:
        /* Deregister the admin queue's interrupt */
        pci_free_irq(pdev, 0, adminq);
 
@@ -2185,25 +2210,34 @@ static int nvme_setup_io_queues(struct nvme_dev *dev)
        result = max(result - 1, 1);
        dev->max_qid = result + dev->io_queues[HCTX_TYPE_POLL];
 
-       dev_info(dev->ctrl.device, "%d/%d/%d default/read/poll queues\n",
-                                       dev->io_queues[HCTX_TYPE_DEFAULT],
-                                       dev->io_queues[HCTX_TYPE_READ],
-                                       dev->io_queues[HCTX_TYPE_POLL]);
-
        /*
         * Should investigate if there's a performance win from allocating
         * more queues than interrupt vectors; it might allow the submission
         * path to scale better, even if the receive path is limited by the
         * number of interrupts.
         */
-
        result = queue_request_irq(adminq);
        if (result) {
                adminq->cq_vector = -1;
                return result;
        }
        set_bit(NVMEQ_ENABLED, &adminq->flags);
-       return nvme_create_io_queues(dev);
+
+       result = nvme_create_io_queues(dev);
+       if (result || dev->online_queues < 2)
+               return result;
+
+       if (dev->online_queues - 1 < dev->max_qid) {
+               nr_io_queues = dev->online_queues - 1;
+               nvme_disable_io_queues(dev);
+               nvme_suspend_io_queues(dev);
+               goto retry;
+       }
+       dev_info(dev->ctrl.device, "%d/%d/%d default/read/poll queues\n",
+                                       dev->io_queues[HCTX_TYPE_DEFAULT],
+                                       dev->io_queues[HCTX_TYPE_READ],
+                                       dev->io_queues[HCTX_TYPE_POLL]);
+       return 0;
 }
 
 static void nvme_del_queue_end(struct request *req, blk_status_t error)
@@ -2248,7 +2282,7 @@ static int nvme_delete_queue(struct nvme_queue *nvmeq, u8 opcode)
        return 0;
 }
 
-static bool nvme_disable_io_queues(struct nvme_dev *dev, u8 opcode)
+static bool __nvme_disable_io_queues(struct nvme_dev *dev, u8 opcode)
 {
        int nr_queues = dev->online_queues - 1, sent = 0;
        unsigned long timeout;
@@ -2294,7 +2328,6 @@ static int nvme_dev_add(struct nvme_dev *dev)
                dev->tagset.nr_maps = 2; /* default + read */
                if (dev->io_queues[HCTX_TYPE_POLL])
                        dev->tagset.nr_maps++;
-               dev->tagset.nr_maps = HCTX_MAX_TYPES;
                dev->tagset.timeout = NVME_IO_TIMEOUT;
                dev->tagset.numa_node = dev_to_node(dev->dev);
                dev->tagset.queue_depth =
@@ -2410,7 +2443,6 @@ static void nvme_pci_disable(struct nvme_dev *dev)
 
 static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
 {
-       int i;
        bool dead = true;
        struct pci_dev *pdev = to_pci_dev(dev->dev);
 
@@ -2437,13 +2469,11 @@ static void nvme_dev_disable(struct nvme_dev *dev, bool shutdown)
        nvme_stop_queues(&dev->ctrl);
 
        if (!dead && dev->ctrl.queue_count > 0) {
-               if (nvme_disable_io_queues(dev, nvme_admin_delete_sq))
-                       nvme_disable_io_queues(dev, nvme_admin_delete_cq);
+               nvme_disable_io_queues(dev);
                nvme_disable_admin_queue(dev, shutdown);
        }
-       for (i = dev->ctrl.queue_count - 1; i >= 0; i--)
-               nvme_suspend_queue(&dev->queues[i]);
-
+       nvme_suspend_io_queues(dev);
+       nvme_suspend_queue(&dev->queues[0]);
        nvme_pci_disable(dev);
 
        blk_mq_tagset_busy_iter(&dev->tagset, nvme_cancel_request, &dev->ctrl);
@@ -2527,27 +2557,18 @@ static void nvme_reset_work(struct work_struct *work)
        if (dev->ctrl.ctrl_config & NVME_CC_ENABLE)
                nvme_dev_disable(dev, false);
 
-       /*
-        * Introduce CONNECTING state from nvme-fc/rdma transports to mark the
-        * initializing procedure here.
-        */
-       if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_CONNECTING)) {
-               dev_warn(dev->ctrl.device,
-                       "failed to mark controller CONNECTING\n");
-               goto out;
-       }
-
+       mutex_lock(&dev->shutdown_lock);
        result = nvme_pci_enable(dev);
        if (result)
-               goto out;
+               goto out_unlock;
 
        result = nvme_pci_configure_admin_queue(dev);
        if (result)
-               goto out;
+               goto out_unlock;
 
        result = nvme_alloc_admin_tags(dev);
        if (result)
-               goto out;
+               goto out_unlock;
 
        /*
         * Limit the max command size to prevent iod->sg allocations going
@@ -2555,6 +2576,17 @@ static void nvme_reset_work(struct work_struct *work)
         */
        dev->ctrl.max_hw_sectors = NVME_MAX_KB_SZ << 1;
        dev->ctrl.max_segments = NVME_MAX_SEGS;
+       mutex_unlock(&dev->shutdown_lock);
+
+       /*
+        * Introduce CONNECTING state from nvme-fc/rdma transports to mark the
+        * initializing procedure here.
+        */
+       if (!nvme_change_ctrl_state(&dev->ctrl, NVME_CTRL_CONNECTING)) {
+               dev_warn(dev->ctrl.device,
+                       "failed to mark controller CONNECTING\n");
+               goto out;
+       }
 
        result = nvme_init_identify(&dev->ctrl);
        if (result)
@@ -2619,6 +2651,8 @@ static void nvme_reset_work(struct work_struct *work)
        nvme_start_ctrl(&dev->ctrl);
        return;
 
+ out_unlock:
+       mutex_unlock(&dev->shutdown_lock);
  out:
        nvme_remove_dead_ctrl(dev, result);
 }
@@ -2946,6 +2980,8 @@ static const struct pci_device_id nvme_id_table[] = {
        { PCI_VDEVICE(INTEL, 0xf1a5),   /* Intel 600P/P3100 */
                .driver_data = NVME_QUIRK_NO_DEEPEST_PS |
                                NVME_QUIRK_MEDIUM_PRIO_SQ },
+       { PCI_VDEVICE(INTEL, 0xf1a6),   /* Intel 760p/Pro 7600p */
+               .driver_data = NVME_QUIRK_IGNORE_DEV_SUBNQN, },
        { PCI_VDEVICE(INTEL, 0x5845),   /* Qemu emulated controller */
                .driver_data = NVME_QUIRK_IDENTIFY_CNS, },
        { PCI_DEVICE(0x1bb1, 0x0100),   /* Seagate Nytro Flash Storage */
index 0a2fd29..52abc3a 100644 (file)
@@ -119,6 +119,7 @@ struct nvme_rdma_ctrl {
 
        struct nvme_ctrl        ctrl;
        bool                    use_inline_data;
+       u32                     io_queues[HCTX_MAX_TYPES];
 };
 
 static inline struct nvme_rdma_ctrl *to_rdma_ctrl(struct nvme_ctrl *ctrl)
@@ -165,8 +166,8 @@ static inline int nvme_rdma_queue_idx(struct nvme_rdma_queue *queue)
 static bool nvme_rdma_poll_queue(struct nvme_rdma_queue *queue)
 {
        return nvme_rdma_queue_idx(queue) >
-               queue->ctrl->ctrl.opts->nr_io_queues +
-               queue->ctrl->ctrl.opts->nr_write_queues;
+               queue->ctrl->io_queues[HCTX_TYPE_DEFAULT] +
+               queue->ctrl->io_queues[HCTX_TYPE_READ];
 }
 
 static inline size_t nvme_rdma_inline_data_size(struct nvme_rdma_queue *queue)
@@ -661,8 +662,21 @@ static int nvme_rdma_alloc_io_queues(struct nvme_rdma_ctrl *ctrl)
        nr_io_queues = min_t(unsigned int, nr_io_queues,
                                ibdev->num_comp_vectors);
 
-       nr_io_queues += min(opts->nr_write_queues, num_online_cpus());
-       nr_io_queues += min(opts->nr_poll_queues, num_online_cpus());
+       if (opts->nr_write_queues) {
+               ctrl->io_queues[HCTX_TYPE_DEFAULT] =
+                               min(opts->nr_write_queues, nr_io_queues);
+               nr_io_queues += ctrl->io_queues[HCTX_TYPE_DEFAULT];
+       } else {
+               ctrl->io_queues[HCTX_TYPE_DEFAULT] = nr_io_queues;
+       }
+
+       ctrl->io_queues[HCTX_TYPE_READ] = nr_io_queues;
+
+       if (opts->nr_poll_queues) {
+               ctrl->io_queues[HCTX_TYPE_POLL] =
+                       min(opts->nr_poll_queues, num_online_cpus());
+               nr_io_queues += ctrl->io_queues[HCTX_TYPE_POLL];
+       }
 
        ret = nvme_set_queue_count(&ctrl->ctrl, &nr_io_queues);
        if (ret)
@@ -1689,18 +1703,28 @@ static enum blk_eh_timer_return
 nvme_rdma_timeout(struct request *rq, bool reserved)
 {
        struct nvme_rdma_request *req = blk_mq_rq_to_pdu(rq);
+       struct nvme_rdma_queue *queue = req->queue;
+       struct nvme_rdma_ctrl *ctrl = queue->ctrl;
 
-       dev_warn(req->queue->ctrl->ctrl.device,
-                "I/O %d QID %d timeout, reset controller\n",
-                rq->tag, nvme_rdma_queue_idx(req->queue));
+       dev_warn(ctrl->ctrl.device, "I/O %d QID %d timeout\n",
+                rq->tag, nvme_rdma_queue_idx(queue));
 
-       /* queue error recovery */
-       nvme_rdma_error_recovery(req->queue->ctrl);
+       if (ctrl->ctrl.state != NVME_CTRL_LIVE) {
+               /*
+                * Teardown immediately if controller times out while starting
+                * or we are already started error recovery. all outstanding
+                * requests are completed on shutdown, so we return BLK_EH_DONE.
+                */
+               flush_work(&ctrl->err_work);
+               nvme_rdma_teardown_io_queues(ctrl, false);
+               nvme_rdma_teardown_admin_queue(ctrl, false);
+               return BLK_EH_DONE;
+       }
 
-       /* fail with DNR on cmd timeout */
-       nvme_req(rq)->status = NVME_SC_ABORT_REQ | NVME_SC_DNR;
+       dev_warn(ctrl->ctrl.device, "starting error recovery\n");
+       nvme_rdma_error_recovery(ctrl);
 
-       return BLK_EH_DONE;
+       return BLK_EH_RESET_TIMER;
 }
 
 static blk_status_t nvme_rdma_queue_rq(struct blk_mq_hw_ctx *hctx,
@@ -1779,17 +1803,15 @@ static int nvme_rdma_map_queues(struct blk_mq_tag_set *set)
        struct nvme_rdma_ctrl *ctrl = set->driver_data;
 
        set->map[HCTX_TYPE_DEFAULT].queue_offset = 0;
-       set->map[HCTX_TYPE_READ].nr_queues = ctrl->ctrl.opts->nr_io_queues;
+       set->map[HCTX_TYPE_DEFAULT].nr_queues =
+                       ctrl->io_queues[HCTX_TYPE_DEFAULT];
+       set->map[HCTX_TYPE_READ].nr_queues = ctrl->io_queues[HCTX_TYPE_READ];
        if (ctrl->ctrl.opts->nr_write_queues) {
                /* separate read/write queues */
-               set->map[HCTX_TYPE_DEFAULT].nr_queues =
-                               ctrl->ctrl.opts->nr_write_queues;
                set->map[HCTX_TYPE_READ].queue_offset =
-                               ctrl->ctrl.opts->nr_write_queues;
+                               ctrl->io_queues[HCTX_TYPE_DEFAULT];
        } else {
                /* mixed read/write queues */
-               set->map[HCTX_TYPE_DEFAULT].nr_queues =
-                               ctrl->ctrl.opts->nr_io_queues;
                set->map[HCTX_TYPE_READ].queue_offset = 0;
        }
        blk_mq_rdma_map_queues(&set->map[HCTX_TYPE_DEFAULT],
@@ -1799,12 +1821,12 @@ static int nvme_rdma_map_queues(struct blk_mq_tag_set *set)
 
        if (ctrl->ctrl.opts->nr_poll_queues) {
                set->map[HCTX_TYPE_POLL].nr_queues =
-                               ctrl->ctrl.opts->nr_poll_queues;
+                               ctrl->io_queues[HCTX_TYPE_POLL];
                set->map[HCTX_TYPE_POLL].queue_offset =
-                               ctrl->ctrl.opts->nr_io_queues;
+                               ctrl->io_queues[HCTX_TYPE_DEFAULT];
                if (ctrl->ctrl.opts->nr_write_queues)
                        set->map[HCTX_TYPE_POLL].queue_offset +=
-                               ctrl->ctrl.opts->nr_write_queues;
+                               ctrl->io_queues[HCTX_TYPE_READ];
                blk_mq_map_queues(&set->map[HCTX_TYPE_POLL]);
        }
        return 0;
index de17491..5f0a004 100644 (file)
@@ -1565,8 +1565,7 @@ static void nvme_tcp_destroy_io_queues(struct nvme_ctrl *ctrl, bool remove)
 {
        nvme_tcp_stop_io_queues(ctrl);
        if (remove) {
-               if (ctrl->ops->flags & NVME_F_FABRICS)
-                       blk_cleanup_queue(ctrl->connect_q);
+               blk_cleanup_queue(ctrl->connect_q);
                blk_mq_free_tag_set(ctrl->tagset);
        }
        nvme_tcp_free_io_queues(ctrl);
@@ -1587,12 +1586,10 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new)
                        goto out_free_io_queues;
                }
 
-               if (ctrl->ops->flags & NVME_F_FABRICS) {
-                       ctrl->connect_q = blk_mq_init_queue(ctrl->tagset);
-                       if (IS_ERR(ctrl->connect_q)) {
-                               ret = PTR_ERR(ctrl->connect_q);
-                               goto out_free_tag_set;
-                       }
+               ctrl->connect_q = blk_mq_init_queue(ctrl->tagset);
+               if (IS_ERR(ctrl->connect_q)) {
+                       ret = PTR_ERR(ctrl->connect_q);
+                       goto out_free_tag_set;
                }
        } else {
                blk_mq_update_nr_hw_queues(ctrl->tagset,
@@ -1606,7 +1603,7 @@ static int nvme_tcp_configure_io_queues(struct nvme_ctrl *ctrl, bool new)
        return 0;
 
 out_cleanup_connect_q:
-       if (new && (ctrl->ops->flags & NVME_F_FABRICS))
+       if (new)
                blk_cleanup_queue(ctrl->connect_q);
 out_free_tag_set:
        if (new)
@@ -1620,7 +1617,6 @@ static void nvme_tcp_destroy_admin_queue(struct nvme_ctrl *ctrl, bool remove)
 {
        nvme_tcp_stop_queue(ctrl, 0);
        if (remove) {
-               free_opal_dev(ctrl->opal_dev);
                blk_cleanup_queue(ctrl->admin_q);
                blk_mq_free_tag_set(ctrl->admin_tagset);
        }
@@ -1952,20 +1948,23 @@ nvme_tcp_timeout(struct request *rq, bool reserved)
        struct nvme_tcp_ctrl *ctrl = req->queue->ctrl;
        struct nvme_tcp_cmd_pdu *pdu = req->pdu;
 
-       dev_dbg(ctrl->ctrl.device,
+       dev_warn(ctrl->ctrl.device,
                "queue %d: timeout request %#x type %d\n",
-               nvme_tcp_queue_id(req->queue), rq->tag,
-               pdu->hdr.type);
+               nvme_tcp_queue_id(req->queue), rq->tag, pdu->hdr.type);
 
        if (ctrl->ctrl.state != NVME_CTRL_LIVE) {
-               union nvme_result res = {};
-
-               nvme_req(rq)->flags |= NVME_REQ_CANCELLED;
-               nvme_end_request(rq, cpu_to_le16(NVME_SC_ABORT_REQ), res);
+               /*
+                * Teardown immediately if controller times out while starting
+                * or we are already started error recovery. all outstanding
+                * requests are completed on shutdown, so we return BLK_EH_DONE.
+                */
+               flush_work(&ctrl->err_work);
+               nvme_tcp_teardown_io_queues(&ctrl->ctrl, false);
+               nvme_tcp_teardown_admin_queue(&ctrl->ctrl, false);
                return BLK_EH_DONE;
        }
 
-       /* queue error recovery */
+       dev_warn(ctrl->ctrl.device, "starting error recovery\n");
        nvme_tcp_error_recovery(&ctrl->ctrl);
 
        return BLK_EH_RESET_TIMER;
index a8d23eb..a884e3a 100644 (file)
@@ -139,6 +139,10 @@ static void nvmet_rdma_recv_done(struct ib_cq *cq, struct ib_wc *wc);
 static void nvmet_rdma_read_data_done(struct ib_cq *cq, struct ib_wc *wc);
 static void nvmet_rdma_qp_event(struct ib_event *event, void *priv);
 static void nvmet_rdma_queue_disconnect(struct nvmet_rdma_queue *queue);
+static void nvmet_rdma_free_rsp(struct nvmet_rdma_device *ndev,
+                               struct nvmet_rdma_rsp *r);
+static int nvmet_rdma_alloc_rsp(struct nvmet_rdma_device *ndev,
+                               struct nvmet_rdma_rsp *r);
 
 static const struct nvmet_fabrics_ops nvmet_rdma_ops;
 
@@ -182,9 +186,17 @@ nvmet_rdma_get_rsp(struct nvmet_rdma_queue *queue)
        spin_unlock_irqrestore(&queue->rsps_lock, flags);
 
        if (unlikely(!rsp)) {
-               rsp = kmalloc(sizeof(*rsp), GFP_KERNEL);
+               int ret;
+
+               rsp = kzalloc(sizeof(*rsp), GFP_KERNEL);
                if (unlikely(!rsp))
                        return NULL;
+               ret = nvmet_rdma_alloc_rsp(queue->dev, rsp);
+               if (unlikely(ret)) {
+                       kfree(rsp);
+                       return NULL;
+               }
+
                rsp->allocated = true;
        }
 
@@ -197,6 +209,7 @@ nvmet_rdma_put_rsp(struct nvmet_rdma_rsp *rsp)
        unsigned long flags;
 
        if (unlikely(rsp->allocated)) {
+               nvmet_rdma_free_rsp(rsp->queue->dev, rsp);
                kfree(rsp);
                return;
        }
index 44b37b2..ad0df78 100644 (file)
@@ -1089,7 +1089,7 @@ out:
 
 static int nvmet_tcp_try_recv_one(struct nvmet_tcp_queue *queue)
 {
-       int result;
+       int result = 0;
 
        if (unlikely(queue->rcv_state == NVMET_TCP_RECV_ERR))
                return 0;
index a09c1c3..49b16f7 100644 (file)
@@ -207,11 +207,8 @@ static void __of_attach_node(struct device_node *np)
 
        if (!of_node_check_flag(np, OF_OVERLAY)) {
                np->name = __of_get_property(np, "name", NULL);
-               np->type = __of_get_property(np, "device_type", NULL);
                if (!np->name)
                        np->name = "<NULL>";
-               if (!np->type)
-                       np->type = "<NULL>";
 
                phandle = __of_get_property(np, "phandle", &sz);
                if (!phandle)
index 7099c65..9cc1461 100644 (file)
@@ -314,12 +314,8 @@ static bool populate_node(const void *blob,
        populate_properties(blob, offset, mem, np, pathp, dryrun);
        if (!dryrun) {
                np->name = of_get_property(np, "name", NULL);
-               np->type = of_get_property(np, "device_type", NULL);
-
                if (!np->name)
                        np->name = "<NULL>";
-               if (!np->type)
-                       np->type = "<NULL>";
        }
 
        *pnp = np;
index 2b5ac43..c423e94 100644 (file)
@@ -423,12 +423,9 @@ static int add_changeset_node(struct overlay_changeset *ovcs,
 
                tchild->parent = target->np;
                tchild->name = __of_get_property(node, "name", NULL);
-               tchild->type = __of_get_property(node, "device_type", NULL);
 
                if (!tchild->name)
                        tchild->name = "<NULL>";
-               if (!tchild->type)
-                       tchild->type = "<NULL>";
 
                /* ignore obsolete "linux,phandle" */
                phandle = __of_get_property(node, "phandle", &size);
index d318506..7eda43c 100644 (file)
@@ -155,7 +155,6 @@ static struct device_node * __init of_pdt_create_node(phandle node,
        dp->parent = parent;
 
        dp->name = of_pdt_get_one_property(node, "name");
-       dp->type = of_pdt_get_one_property(node, "device_type");
        dp->phandle = node;
 
        dp->properties = of_pdt_build_prop_list(node);
index 0843003..8631efa 100644 (file)
@@ -806,6 +806,7 @@ struct device_node *of_graph_get_remote_node(const struct device_node *node,
 
        if (!of_device_is_available(remote)) {
                pr_debug("not available for remote node\n");
+               of_node_put(remote);
                return NULL;
        }
 
index e5507ad..18f1639 100644 (file)
@@ -988,11 +988,9 @@ void _opp_free(struct dev_pm_opp *opp)
        kfree(opp);
 }
 
-static void _opp_kref_release(struct kref *kref)
+static void _opp_kref_release(struct dev_pm_opp *opp,
+                             struct opp_table *opp_table)
 {
-       struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
-       struct opp_table *opp_table = opp->opp_table;
-
        /*
         * Notify the changes in the availability of the operable
         * frequency/voltage list.
@@ -1002,7 +1000,22 @@ static void _opp_kref_release(struct kref *kref)
        opp_debug_remove_one(opp);
        list_del(&opp->node);
        kfree(opp);
+}
 
+static void _opp_kref_release_unlocked(struct kref *kref)
+{
+       struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
+       struct opp_table *opp_table = opp->opp_table;
+
+       _opp_kref_release(opp, opp_table);
+}
+
+static void _opp_kref_release_locked(struct kref *kref)
+{
+       struct dev_pm_opp *opp = container_of(kref, struct dev_pm_opp, kref);
+       struct opp_table *opp_table = opp->opp_table;
+
+       _opp_kref_release(opp, opp_table);
        mutex_unlock(&opp_table->lock);
 }
 
@@ -1013,10 +1026,16 @@ void dev_pm_opp_get(struct dev_pm_opp *opp)
 
 void dev_pm_opp_put(struct dev_pm_opp *opp)
 {
-       kref_put_mutex(&opp->kref, _opp_kref_release, &opp->opp_table->lock);
+       kref_put_mutex(&opp->kref, _opp_kref_release_locked,
+                      &opp->opp_table->lock);
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_put);
 
+static void dev_pm_opp_put_unlocked(struct dev_pm_opp *opp)
+{
+       kref_put(&opp->kref, _opp_kref_release_unlocked);
+}
+
 /**
  * dev_pm_opp_remove()  - Remove an OPP from OPP table
  * @dev:       device for which we do this operation
@@ -1060,6 +1079,40 @@ void dev_pm_opp_remove(struct device *dev, unsigned long freq)
 }
 EXPORT_SYMBOL_GPL(dev_pm_opp_remove);
 
+/**
+ * dev_pm_opp_remove_all_dynamic() - Remove all dynamically created OPPs
+ * @dev:       device for which we do this operation
+ *
+ * This function removes all dynamically created OPPs from the opp table.
+ */
+void dev_pm_opp_remove_all_dynamic(struct device *dev)
+{
+       struct opp_table *opp_table;
+       struct dev_pm_opp *opp, *temp;
+       int count = 0;
+
+       opp_table = _find_opp_table(dev);
+       if (IS_ERR(opp_table))
+               return;
+
+       mutex_lock(&opp_table->lock);
+       list_for_each_entry_safe(opp, temp, &opp_table->opp_list, node) {
+               if (opp->dynamic) {
+                       dev_pm_opp_put_unlocked(opp);
+                       count++;
+               }
+       }
+       mutex_unlock(&opp_table->lock);
+
+       /* Drop the references taken by dev_pm_opp_add() */
+       while (count--)
+               dev_pm_opp_put_opp_table(opp_table);
+
+       /* Drop the reference taken by _find_opp_table() */
+       dev_pm_opp_put_opp_table(opp_table);
+}
+EXPORT_SYMBOL_GPL(dev_pm_opp_remove_all_dynamic);
+
 struct dev_pm_opp *_opp_allocate(struct opp_table *table)
 {
        struct dev_pm_opp *opp;
index 4310c7a..2ab9240 100644 (file)
@@ -21,13 +21,14 @@ menuconfig PCI
          support for PCI-X and the foundations for PCI Express support.
          Say 'Y' here unless you know what you are doing.
 
+if PCI
+
 config PCI_DOMAINS
        bool
        depends on PCI
 
 config PCI_DOMAINS_GENERIC
        bool
-       depends on PCI
        select PCI_DOMAINS
 
 config PCI_SYSCALL
@@ -37,7 +38,6 @@ source "drivers/pci/pcie/Kconfig"
 
 config PCI_MSI
        bool "Message Signaled Interrupts (MSI and MSI-X)"
-       depends on PCI
        select GENERIC_MSI_IRQ
        help
           This allows device drivers to enable MSI (Message Signaled
@@ -59,7 +59,6 @@ config PCI_MSI_IRQ_DOMAIN
 config PCI_QUIRKS
        default y
        bool "Enable PCI quirk workarounds" if EXPERT
-       depends on PCI
        help
          This enables workarounds for various PCI chipset bugs/quirks.
          Disable this only if your target machine is unaffected by PCI
@@ -67,7 +66,7 @@ config PCI_QUIRKS
 
 config PCI_DEBUG
        bool "PCI Debugging"
-       depends on PCI && DEBUG_KERNEL
+       depends on DEBUG_KERNEL
        help
          Say Y here if you want the PCI core to produce a bunch of debug
          messages to the system log.  Select this if you are having a
@@ -77,7 +76,6 @@ config PCI_DEBUG
 
 config PCI_REALLOC_ENABLE_AUTO
        bool "Enable PCI resource re-allocation detection"
-       depends on PCI
        depends on PCI_IOV
        help
          Say Y here if you want the PCI core to detect if PCI resource
@@ -90,7 +88,6 @@ config PCI_REALLOC_ENABLE_AUTO
 
 config PCI_STUB
        tristate "PCI Stub driver"
-       depends on PCI
        help
          Say Y or M here if you want be able to reserve a PCI device
          when it is going to be assigned to a guest operating system.
@@ -99,7 +96,6 @@ config PCI_STUB
 
 config PCI_PF_STUB
        tristate "PCI PF Stub driver"
-       depends on PCI
        depends on PCI_IOV
        help
          Say Y or M here if you want to enable support for devices that
@@ -111,7 +107,7 @@ config PCI_PF_STUB
 
 config XEN_PCIDEV_FRONTEND
         tristate "Xen PCI Frontend"
-        depends on PCI && X86 && XEN
+        depends on X86 && XEN
         select PCI_XEN
        select XEN_XENBUS_FRONTEND
         default y
@@ -133,7 +129,6 @@ config PCI_BRIDGE_EMUL
 
 config PCI_IOV
        bool "PCI IOV support"
-       depends on PCI
        select PCI_ATS
        help
          I/O Virtualization is a PCI feature supported by some devices
@@ -144,7 +139,6 @@ config PCI_IOV
 
 config PCI_PRI
        bool "PCI PRI support"
-       depends on PCI
        select PCI_ATS
        help
          PRI is the PCI Page Request Interface. It allows PCI devices that are
@@ -154,7 +148,6 @@ config PCI_PRI
 
 config PCI_PASID
        bool "PCI PASID support"
-       depends on PCI
        select PCI_ATS
        help
          Process Address Space Identifiers (PASIDs) can be used by PCI devices
@@ -167,7 +160,7 @@ config PCI_PASID
 
 config PCI_P2PDMA
        bool "PCI peer-to-peer transfer support"
-       depends on PCI && ZONE_DEVICE
+       depends on ZONE_DEVICE
        select GENERIC_ALLOCATOR
        help
          EnableÑ• drivers to do PCI peer-to-peer transactions to and from
@@ -184,12 +177,11 @@ config PCI_P2PDMA
 
 config PCI_LABEL
        def_bool y if (DMI || ACPI)
-       depends on PCI
        select NLS
 
 config PCI_HYPERV
         tristate "Hyper-V PCI Frontend"
-        depends on PCI && X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64
+        depends on X86 && HYPERV && PCI_MSI && PCI_MSI_IRQ_DOMAIN && X86_64
         help
           The PCI device frontend driver allows the kernel to import arbitrary
           PCI devices from a PCI backend to support PCI driver domains.
@@ -198,3 +190,5 @@ source "drivers/pci/hotplug/Kconfig"
 source "drivers/pci/controller/Kconfig"
 source "drivers/pci/endpoint/Kconfig"
 source "drivers/pci/switch/Kconfig"
+
+endif
index 52e47da..80f8430 100644 (file)
@@ -310,6 +310,9 @@ static int imx6_pcie_attach_pd(struct device *dev)
        imx6_pcie->pd_pcie = dev_pm_domain_attach_by_name(dev, "pcie");
        if (IS_ERR(imx6_pcie->pd_pcie))
                return PTR_ERR(imx6_pcie->pd_pcie);
+       /* Do nothing when power domain missing */
+       if (!imx6_pcie->pd_pcie)
+               return 0;
        link = device_link_add(dev, imx6_pcie->pd_pcie,
                        DL_FLAG_STATELESS |
                        DL_FLAG_PM_RUNTIME |
@@ -323,13 +326,13 @@ static int imx6_pcie_attach_pd(struct device *dev)
        if (IS_ERR(imx6_pcie->pd_pcie_phy))
                return PTR_ERR(imx6_pcie->pd_pcie_phy);
 
-       device_link_add(dev, imx6_pcie->pd_pcie_phy,
+       link = device_link_add(dev, imx6_pcie->pd_pcie_phy,
                        DL_FLAG_STATELESS |
                        DL_FLAG_PM_RUNTIME |
                        DL_FLAG_RPM_ACTIVE);
-       if (IS_ERR(link)) {
-               dev_err(dev, "Failed to add device_link to pcie_phy pd: %ld\n", PTR_ERR(link));
-               return PTR_ERR(link);
+       if (!link) {
+               dev_err(dev, "Failed to add device_link to pcie_phy pd.\n");
+               return -EINVAL;
        }
 
        return 0;
index 241ebe0..e35e9ea 100644 (file)
@@ -8,6 +8,7 @@
 
 #include <linux/clk.h>
 #include <linux/delay.h>
+#include <linux/gpio/consumer.h>
 #include <linux/of_device.h>
 #include <linux/of_gpio.h>
 #include <linux/pci.h>
index b171b6b..0c389a3 100644 (file)
@@ -22,7 +22,6 @@
 #include <linux/resource.h>
 #include <linux/of_pci.h>
 #include <linux/of_irq.h>
-#include <linux/gpio/consumer.h>
 
 #include "pcie-designware.h"
 
@@ -30,7 +29,6 @@ struct armada8k_pcie {
        struct dw_pcie *pci;
        struct clk *clk;
        struct clk *clk_reg;
-       struct gpio_desc *reset_gpio;
 };
 
 #define PCIE_VENDOR_REGS_OFFSET                0x8000
@@ -139,12 +137,6 @@ static int armada8k_pcie_host_init(struct pcie_port *pp)
        struct dw_pcie *pci = to_dw_pcie_from_pp(pp);
        struct armada8k_pcie *pcie = to_armada8k_pcie(pci);
 
-       if (pcie->reset_gpio) {
-               /* assert and then deassert the reset signal */
-               gpiod_set_value_cansleep(pcie->reset_gpio, 1);
-               msleep(100);
-               gpiod_set_value_cansleep(pcie->reset_gpio, 0);
-       }
        dw_pcie_setup_rc(pp);
        armada8k_pcie_establish_link(pcie);
 
@@ -257,14 +249,6 @@ static int armada8k_pcie_probe(struct platform_device *pdev)
                goto fail_clkreg;
        }
 
-       /* Get reset gpio signal and hold asserted (logically high) */
-       pcie->reset_gpio = devm_gpiod_get_optional(dev, "reset",
-                                                  GPIOD_OUT_HIGH);
-       if (IS_ERR(pcie->reset_gpio)) {
-               ret = PTR_ERR(pcie->reset_gpio);
-               goto fail_clkreg;
-       }
-
        platform_set_drvdata(pdev, pcie);
 
        ret = armada8k_add_pcie_port(pcie, pdev);
index 9deb569..cb3401a 100644 (file)
@@ -602,9 +602,9 @@ int iproc_msi_init(struct iproc_pcie *pcie, struct device_node *node)
        }
 
        /* Reserve memory for event queue and make sure memories are zeroed */
-       msi->eq_cpu = dma_zalloc_coherent(pcie->dev,
-                                         msi->nr_eq_region * EQ_MEM_REGION_SIZE,
-                                         &msi->eq_dma, GFP_KERNEL);
+       msi->eq_cpu = dma_alloc_coherent(pcie->dev,
+                                        msi->nr_eq_region * EQ_MEM_REGION_SIZE,
+                                        &msi->eq_dma, GFP_KERNEL);
        if (!msi->eq_cpu) {
                ret = -ENOMEM;
                goto free_irqs;
index 7a1c8a0..4c0b478 100644 (file)
@@ -1168,7 +1168,8 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
                                   const struct irq_affinity *affd)
 {
        static const struct irq_affinity msi_default_affd;
-       int vecs = -ENOSPC;
+       int msix_vecs = -ENOSPC;
+       int msi_vecs = -ENOSPC;
 
        if (flags & PCI_IRQ_AFFINITY) {
                if (!affd)
@@ -1179,16 +1180,17 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
        }
 
        if (flags & PCI_IRQ_MSIX) {
-               vecs = __pci_enable_msix_range(dev, NULL, min_vecs, max_vecs,
-                               affd);
-               if (vecs > 0)
-                       return vecs;
+               msix_vecs = __pci_enable_msix_range(dev, NULL, min_vecs,
+                                                   max_vecs, affd);
+               if (msix_vecs > 0)
+                       return msix_vecs;
        }
 
        if (flags & PCI_IRQ_MSI) {
-               vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs, affd);
-               if (vecs > 0)
-                       return vecs;
+               msi_vecs = __pci_enable_msi_range(dev, min_vecs, max_vecs,
+                                                 affd);
+               if (msi_vecs > 0)
+                       return msi_vecs;
        }
 
        /* use legacy irq if allowed */
@@ -1199,7 +1201,9 @@ int pci_alloc_irq_vectors_affinity(struct pci_dev *dev, unsigned int min_vecs,
                }
        }
 
-       return vecs;
+       if (msix_vecs == -ENOSPC)
+               return -ENOSPC;
+       return msi_vecs;
 }
 EXPORT_SYMBOL(pci_alloc_irq_vectors_affinity);
 
index c9d8e3c..c25acac 100644 (file)
@@ -6195,7 +6195,8 @@ static int __init pci_setup(char *str)
                        } else if (!strncmp(str, "pcie_scan_all", 13)) {
                                pci_add_flags(PCI_SCAN_ALL_PCIE_DEVS);
                        } else if (!strncmp(str, "disable_acs_redir=", 18)) {
-                               disable_acs_redir_param = str + 18;
+                               disable_acs_redir_param =
+                                       kstrdup(str + 18, GFP_KERNEL);
                        } else {
                                printk(KERN_ERR "PCI: Unknown option `%s'\n",
                                                str);
index b0a413f..e2a879e 100644 (file)
@@ -639,8 +639,9 @@ static void quirk_synopsys_haps(struct pci_dev *pdev)
                break;
        }
 }
-DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_SYNOPSYS, PCI_ANY_ID,
-                        quirk_synopsys_haps);
+DECLARE_PCI_FIXUP_CLASS_HEADER(PCI_VENDOR_ID_SYNOPSYS, PCI_ANY_ID,
+                              PCI_CLASS_SERIAL_USB_XHCI, 0,
+                              quirk_synopsys_haps);
 
 /*
  * Let's make the southbridge information explicit instead of having to
index 6c5536d..e22766c 100644 (file)
@@ -1373,10 +1373,10 @@ static int switchtec_init_pci(struct switchtec_dev *stdev,
        if (ioread32(&stdev->mmio_mrpc->dma_ver) == 0)
                return 0;
 
-       stdev->dma_mrpc = dma_zalloc_coherent(&stdev->pdev->dev,
-                                             sizeof(*stdev->dma_mrpc),
-                                             &stdev->dma_mrpc_dma_addr,
-                                             GFP_KERNEL);
+       stdev->dma_mrpc = dma_alloc_coherent(&stdev->pdev->dev,
+                                            sizeof(*stdev->dma_mrpc),
+                                            &stdev->dma_mrpc_dma_addr,
+                                            GFP_KERNEL);
        if (stdev->dma_mrpc == NULL)
                return -ENOMEM;
 
index a91fc67..d70ba9b 100644 (file)
@@ -32,7 +32,7 @@
 
 /* register 0x01 */
 #define REF_FREF_SEL_25                BIT(0)
-#define PHY_MODE_SATA          (0x0 << 5)
+#define PHY_BERLIN_MODE_SATA   (0x0 << 5)
 
 /* register 0x02 */
 #define USE_MAX_PLL_RATE       BIT(12)
@@ -102,7 +102,8 @@ static int phy_berlin_sata_power_on(struct phy *phy)
 
        /* set PHY mode and ref freq to 25 MHz */
        phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x01,
-                                   0x00ff, REF_FREF_SEL_25 | PHY_MODE_SATA);
+                                   0x00ff,
+                                   REF_FREF_SEL_25 | PHY_BERLIN_MODE_SATA);
 
        /* set PHY up to 6 Gbps */
        phy_berlin_sata_reg_setbits(ctrl_reg, priv->phy_base, 0x25,
index 6fd6e07..09a77e5 100644 (file)
@@ -31,7 +31,7 @@ static int ath79_usb_phy_power_on(struct phy *phy)
 
        err = reset_control_deassert(priv->reset);
        if (err && priv->no_suspend_override)
-               reset_control_assert(priv->no_suspend_override);
+               reset_control_deassert(priv->no_suspend_override);
 
        return err;
 }
@@ -69,7 +69,7 @@ static int ath79_usb_phy_probe(struct platform_device *pdev)
        if (!priv)
                return -ENOMEM;
 
-       priv->reset = devm_reset_control_get(&pdev->dev, "usb-phy");
+       priv->reset = devm_reset_control_get(&pdev->dev, "phy");
        if (IS_ERR(priv->reset))
                return PTR_ERR(priv->reset);
 
index f137e01..c4709ed 100644 (file)
@@ -82,6 +82,7 @@ config PHY_TI_GMII_SEL
        default y if TI_CPSW=y
        depends on TI_CPSW || COMPILE_TEST
        select GENERIC_PHY
+       select REGMAP
        default m
        help
          This driver supports configuring of the TI CPSW Port mode depending on
index 77fdaa5..a52c5bb 100644 (file)
@@ -204,11 +204,11 @@ static struct phy *phy_gmii_sel_of_xlate(struct device *dev,
 
        if (args->args_count < 1)
                return ERR_PTR(-EINVAL);
+       if (!priv || !priv->if_phys)
+               return ERR_PTR(-ENODEV);
        if (priv->soc_data->features & BIT(PHY_GMII_SEL_RMII_IO_CLK_EN) &&
            args->args_count < 2)
                return ERR_PTR(-EINVAL);
-       if (!priv || !priv->if_phys)
-               return ERR_PTR(-ENODEV);
        if (phy_id > priv->soc_data->num_ports)
                return ERR_PTR(-EINVAL);
        if (phy_id != priv->if_phys[phy_id - 1].id)
index 05044e3..03ec7a5 100644 (file)
@@ -1513,7 +1513,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
                        DMI_MATCH(DMI_PRODUCT_FAMILY, "Intel_Strago"),
-                       DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {
@@ -1521,7 +1521,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "HP"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Setzer"),
-                       DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {
@@ -1529,7 +1529,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Cyan"),
-                       DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {
@@ -1537,7 +1537,7 @@ static const struct dmi_system_id chv_no_valid_mask[] = {
                .matches = {
                        DMI_MATCH(DMI_SYS_VENDOR, "GOOGLE"),
                        DMI_MATCH(DMI_PRODUCT_NAME, "Celes"),
-                       DMI_MATCH(DMI_BOARD_VERSION, "1.0"),
+                       DMI_MATCH(DMI_PRODUCT_VERSION, "1.0"),
                },
        },
        {}
index 1817786..a005cbc 100644 (file)
@@ -45,12 +45,14 @@ config PINCTRL_MT2701
 config PINCTRL_MT7623
        bool "Mediatek MT7623 pin control with generic binding"
        depends on MACH_MT7623 || COMPILE_TEST
+       depends on OF
        default MACH_MT7623
        select PINCTRL_MTK_MOORE
 
 config PINCTRL_MT7629
        bool "Mediatek MT7629 pin control"
        depends on MACH_MT7629 || COMPILE_TEST
+       depends on OF
        default MACH_MT7629
        select PINCTRL_MTK_MOORE
 
@@ -92,6 +94,7 @@ config PINCTRL_MT6797
 
 config PINCTRL_MT7622
        bool "MediaTek MT7622 pin control"
+       depends on OF
        depends on ARM64 || COMPILE_TEST
        default ARM64 && ARCH_MEDIATEK
        select PINCTRL_MTK_MOORE
index c69ca95..0f140a8 100644 (file)
@@ -693,7 +693,7 @@ static const char * const sd_a_groups[] = {
 
 static const char * const sdxc_a_groups[] = {
        "sdxc_d0_0_a", "sdxc_d13_0_a", "sdxc_d47_a", "sdxc_clk_a",
-       "sdxc_cmd_a", "sdxc_d0_1_a", "sdxc_d0_13_1_a"
+       "sdxc_cmd_a", "sdxc_d0_1_a", "sdxc_d13_1_a"
 };
 
 static const char * const pcm_a_groups[] = {
index b03481e..98905d4 100644 (file)
@@ -832,8 +832,13 @@ static int mcp23s08_probe_one(struct mcp23s08 *mcp, struct device *dev,
                break;
 
        case MCP_TYPE_S18:
+               one_regmap_config =
+                       devm_kmemdup(dev, &mcp23x17_regmap,
+                               sizeof(struct regmap_config), GFP_KERNEL);
+               if (!one_regmap_config)
+                       return -ENOMEM;
                mcp->regmap = devm_regmap_init(dev, &mcp23sxx_spi_regmap, mcp,
-                                              &mcp23x17_regmap);
+                                              one_regmap_config);
                mcp->reg_shift = 1;
                mcp->chip.ngpio = 16;
                mcp->chip.label = "mcp23s18";
index 7aae52a..4ffd56f 100644 (file)
@@ -79,7 +79,7 @@ enum {
                .intr_cfg_reg = 0,                      \
                .intr_status_reg = 0,                   \
                .intr_target_reg = 0,                   \
-               .tile = NORTH,                          \
+               .tile = SOUTH,                          \
                .mux_bit = -1,                          \
                .pull_bit = pull,                       \
                .drv_bit = drv,                         \
index aa8b581..ef4268c 100644 (file)
@@ -588,7 +588,7 @@ static const unsigned int h6_irq_bank_map[] = { 1, 5, 6, 7 };
 static const struct sunxi_pinctrl_desc h6_pinctrl_data = {
        .pins = h6_pins,
        .npins = ARRAY_SIZE(h6_pins),
-       .irq_banks = 3,
+       .irq_banks = 4,
        .irq_bank_map = h6_irq_bank_map,
        .irq_read_needs_mux = true,
 };
index 5d9184d..0e7fa69 100644 (file)
@@ -698,26 +698,24 @@ static int sunxi_pmx_request(struct pinctrl_dev *pctldev, unsigned offset)
 {
        struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
        unsigned short bank = offset / PINS_PER_BANK;
-       struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank];
-       struct regulator *reg;
+       unsigned short bank_offset = bank - pctl->desc->pin_base /
+                                           PINS_PER_BANK;
+       struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset];
+       struct regulator *reg = s_reg->regulator;
+       char supply[16];
        int ret;
 
-       reg = s_reg->regulator;
-       if (!reg) {
-               char supply[16];
-
-               snprintf(supply, sizeof(supply), "vcc-p%c", 'a' + bank);
-               reg = regulator_get(pctl->dev, supply);
-               if (IS_ERR(reg)) {
-                       dev_err(pctl->dev, "Couldn't get bank P%c regulator\n",
-                               'A' + bank);
-                       return PTR_ERR(reg);
-               }
-
-               s_reg->regulator = reg;
-               refcount_set(&s_reg->refcount, 1);
-       } else {
+       if (reg) {
                refcount_inc(&s_reg->refcount);
+               return 0;
+       }
+
+       snprintf(supply, sizeof(supply), "vcc-p%c", 'a' + bank);
+       reg = regulator_get(pctl->dev, supply);
+       if (IS_ERR(reg)) {
+               dev_err(pctl->dev, "Couldn't get bank P%c regulator\n",
+                       'A' + bank);
+               return PTR_ERR(reg);
        }
 
        ret = regulator_enable(reg);
@@ -727,13 +725,13 @@ static int sunxi_pmx_request(struct pinctrl_dev *pctldev, unsigned offset)
                goto out;
        }
 
+       s_reg->regulator = reg;
+       refcount_set(&s_reg->refcount, 1);
+
        return 0;
 
 out:
-       if (refcount_dec_and_test(&s_reg->refcount)) {
-               regulator_put(s_reg->regulator);
-               s_reg->regulator = NULL;
-       }
+       regulator_put(s_reg->regulator);
 
        return ret;
 }
@@ -742,7 +740,9 @@ static int sunxi_pmx_free(struct pinctrl_dev *pctldev, unsigned offset)
 {
        struct sunxi_pinctrl *pctl = pinctrl_dev_get_drvdata(pctldev);
        unsigned short bank = offset / PINS_PER_BANK;
-       struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank];
+       unsigned short bank_offset = bank - pctl->desc->pin_base /
+                                           PINS_PER_BANK;
+       struct sunxi_pinctrl_regulator *s_reg = &pctl->regulators[bank_offset];
 
        if (!refcount_dec_and_test(&s_reg->refcount))
                return 0;
index e340d2a..034c031 100644 (file)
@@ -136,7 +136,7 @@ struct sunxi_pinctrl {
        struct gpio_chip                *chip;
        const struct sunxi_pinctrl_desc *desc;
        struct device                   *dev;
-       struct sunxi_pinctrl_regulator  regulators[12];
+       struct sunxi_pinctrl_regulator  regulators[9];
        struct irq_domain               *domain;
        struct sunxi_pinctrl_function   *functions;
        unsigned                        nfunctions;
index e3b62c2..b5e9db8 100644 (file)
@@ -905,6 +905,7 @@ config TOSHIBA_WMI
 config ACPI_CMPC
        tristate "CMPC Laptop Extras"
        depends on ACPI && INPUT
+       depends on BACKLIGHT_LCD_SUPPORT
        depends on RFKILL || RFKILL=n
        select BACKLIGHT_CLASS_DEVICE
        help
@@ -1009,7 +1010,7 @@ config INTEL_MFLD_THERMAL
 
 config INTEL_IPS
        tristate "Intel Intelligent Power Sharing"
-       depends on ACPI
+       depends on ACPI && PCI
        ---help---
          Intel Calpella platforms support dynamic power sharing between the
          CPU and GPU, maximizing performance in a given TDP.  This driver,
@@ -1128,6 +1129,7 @@ config INTEL_OAKTRAIL
 config SAMSUNG_Q10
        tristate "Samsung Q10 Extras"
        depends on ACPI
+       depends on BACKLIGHT_LCD_SUPPORT
        select BACKLIGHT_CLASS_DEVICE
        ---help---
          This driver provides support for backlight control on Samsung Q10
@@ -1135,7 +1137,7 @@ config SAMSUNG_Q10
 
 config APPLE_GMUX
        tristate "Apple Gmux Driver"
-       depends on ACPI
+       depends on ACPI && PCI
        depends on PNP
        depends on BACKLIGHT_CLASS_DEVICE
        depends on BACKLIGHT_APPLE=n || BACKLIGHT_APPLE
@@ -1174,7 +1176,7 @@ config INTEL_SMARTCONNECT
 
 config INTEL_PMC_IPC
        tristate "Intel PMC IPC Driver"
-       depends on ACPI
+       depends on ACPI && PCI
        ---help---
        This driver provides support for PMC control on some Intel platforms.
        The PMC is an ARC processor which defines IPC commands for communication
index 797fab3..7cbea79 100644 (file)
@@ -224,7 +224,8 @@ long ptp_ioctl(struct posix_clock *pc, unsigned int cmd, unsigned long arg)
                        extoff = NULL;
                        break;
                }
-               if (extoff->n_samples > PTP_MAX_SAMPLES) {
+               if (extoff->n_samples > PTP_MAX_SAMPLES
+                   || extoff->rsv[0] || extoff->rsv[1] || extoff->rsv[2]) {
                        err = -EINVAL;
                        break;
                }
index bb65585..b64c56c 100644 (file)
@@ -1382,9 +1382,9 @@ static int tsi721_doorbell_init(struct tsi721_device *priv)
        INIT_WORK(&priv->idb_work, tsi721_db_dpc);
 
        /* Allocate buffer for inbound doorbells queue */
-       priv->idb_base = dma_zalloc_coherent(&priv->pdev->dev,
-                               IDB_QSIZE * TSI721_IDB_ENTRY_SIZE,
-                               &priv->idb_dma, GFP_KERNEL);
+       priv->idb_base = dma_alloc_coherent(&priv->pdev->dev,
+                                           IDB_QSIZE * TSI721_IDB_ENTRY_SIZE,
+                                           &priv->idb_dma, GFP_KERNEL);
        if (!priv->idb_base)
                return -ENOMEM;
 
@@ -1447,9 +1447,9 @@ static int tsi721_bdma_maint_init(struct tsi721_device *priv)
        regs = priv->regs + TSI721_DMAC_BASE(TSI721_DMACH_MAINT);
 
        /* Allocate space for DMA descriptors */
-       bd_ptr = dma_zalloc_coherent(&priv->pdev->dev,
-                                       bd_num * sizeof(struct tsi721_dma_desc),
-                                       &bd_phys, GFP_KERNEL);
+       bd_ptr = dma_alloc_coherent(&priv->pdev->dev,
+                                   bd_num * sizeof(struct tsi721_dma_desc),
+                                   &bd_phys, GFP_KERNEL);
        if (!bd_ptr)
                return -ENOMEM;
 
@@ -1464,7 +1464,7 @@ static int tsi721_bdma_maint_init(struct tsi721_device *priv)
        sts_size = (bd_num >= TSI721_DMA_MINSTSSZ) ?
                                        bd_num : TSI721_DMA_MINSTSSZ;
        sts_size = roundup_pow_of_two(sts_size);
-       sts_ptr = dma_zalloc_coherent(&priv->pdev->dev,
+       sts_ptr = dma_alloc_coherent(&priv->pdev->dev,
                                     sts_size * sizeof(struct tsi721_dma_sts),
                                     &sts_phys, GFP_KERNEL);
        if (!sts_ptr) {
@@ -1939,10 +1939,10 @@ static int tsi721_open_outb_mbox(struct rio_mport *mport, void *dev_id,
 
        /* Outbound message descriptor status FIFO allocation */
        priv->omsg_ring[mbox].sts_size = roundup_pow_of_two(entries + 1);
-       priv->omsg_ring[mbox].sts_base = dma_zalloc_coherent(&priv->pdev->dev,
-                       priv->omsg_ring[mbox].sts_size *
-                                               sizeof(struct tsi721_dma_sts),
-                       &priv->omsg_ring[mbox].sts_phys, GFP_KERNEL);
+       priv->omsg_ring[mbox].sts_base = dma_alloc_coherent(&priv->pdev->dev,
+                                                           priv->omsg_ring[mbox].sts_size * sizeof(struct tsi721_dma_sts),
+                                                           &priv->omsg_ring[mbox].sts_phys,
+                                                           GFP_KERNEL);
        if (priv->omsg_ring[mbox].sts_base == NULL) {
                tsi_debug(OMSG, &priv->pdev->dev,
                        "ENOMEM for OB_MSG_%d status FIFO", mbox);
index 006ea5a..7f5d443 100644 (file)
@@ -90,9 +90,9 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan, int bd_num)
         * Allocate space for DMA descriptors
         * (add an extra element for link descriptor)
         */
-       bd_ptr = dma_zalloc_coherent(dev,
-                               (bd_num + 1) * sizeof(struct tsi721_dma_desc),
-                               &bd_phys, GFP_ATOMIC);
+       bd_ptr = dma_alloc_coherent(dev,
+                                   (bd_num + 1) * sizeof(struct tsi721_dma_desc),
+                                   &bd_phys, GFP_ATOMIC);
        if (!bd_ptr)
                return -ENOMEM;
 
@@ -108,7 +108,7 @@ static int tsi721_bdma_ch_init(struct tsi721_bdma_chan *bdma_chan, int bd_num)
        sts_size = ((bd_num + 1) >= TSI721_DMA_MINSTSSZ) ?
                                        (bd_num + 1) : TSI721_DMA_MINSTSSZ;
        sts_size = roundup_pow_of_two(sts_size);
-       sts_ptr = dma_zalloc_coherent(dev,
+       sts_ptr = dma_alloc_coherent(dev,
                                     sts_size * sizeof(struct tsi721_dma_sts),
                                     &sts_phys, GFP_ATOMIC);
        if (!sts_ptr) {
index 183fc42..2d7cd34 100644 (file)
@@ -153,10 +153,15 @@ static int rproc_virtio_find_vqs(struct virtio_device *vdev, unsigned int nvqs,
                                 const bool * ctx,
                                 struct irq_affinity *desc)
 {
-       int i, ret;
+       int i, ret, queue_idx = 0;
 
        for (i = 0; i < nvqs; ++i) {
-               vqs[i] = rp_find_vq(vdev, i, callbacks[i], names[i],
+               if (!names[i]) {
+                       vqs[i] = NULL;
+                       continue;
+               }
+
+               vqs[i] = rp_find_vq(vdev, queue_idx++, callbacks[i], names[i],
                                    ctx ? ctx[i] : false);
                if (IS_ERR(vqs[i])) {
                        ret = PTR_ERR(vqs[i]);
index c21da9f..2e01bd8 100644 (file)
@@ -109,7 +109,7 @@ config RESET_QCOM_PDC
 
 config RESET_SIMPLE
        bool "Simple Reset Controller Driver" if COMPILE_TEST
-       default ARCH_SOCFPGA || ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED
+       default ARCH_STM32 || ARCH_STRATIX10 || ARCH_SUNXI || ARCH_ZX || ARCH_ASPEED
        help
          This enables a simple reset controller driver for reset lines that
          that can be asserted and deasserted by toggling bits in a contiguous,
@@ -128,6 +128,14 @@ config RESET_STM32MP157
        help
          This enables the RCC reset controller driver for STM32 MPUs.
 
+config RESET_SOCFPGA
+       bool "SoCFPGA Reset Driver" if COMPILE_TEST && !ARCH_SOCFPGA
+       default ARCH_SOCFPGA
+       select RESET_SIMPLE
+       help
+         This enables the reset driver for the SoCFPGA ARMv7 platforms. This
+         driver gets initialized early during platform init calls.
+
 config RESET_SUNXI
        bool "Allwinner SoCs Reset Driver" if COMPILE_TEST && !ARCH_SUNXI
        default ARCH_SUNXI
@@ -163,15 +171,15 @@ config RESET_UNIPHIER
          Say Y if you want to control reset signals provided by System Control
          block, Media I/O block, Peripheral Block.
 
-config RESET_UNIPHIER_USB3
-       tristate "USB3 reset driver for UniPhier SoCs"
+config RESET_UNIPHIER_GLUE
+       tristate "Reset driver in glue layer for UniPhier SoCs"
        depends on (ARCH_UNIPHIER || COMPILE_TEST) && OF
        default ARCH_UNIPHIER
        select RESET_SIMPLE
        help
-         Support for the USB3 core reset on UniPhier SoCs.
-         Say Y if you want to control reset signals provided by
-         USB3 glue layer.
+         Support for peripheral core reset included in its own glue layer
+         on UniPhier SoCs. Say Y if you want to control reset signals
+         provided by the glue layer.
 
 config RESET_ZYNQ
        bool "ZYNQ Reset Driver" if COMPILE_TEST
index d08e8b9..dc7874d 100644 (file)
@@ -19,10 +19,11 @@ obj-$(CONFIG_RESET_QCOM_AOSS) += reset-qcom-aoss.o
 obj-$(CONFIG_RESET_QCOM_PDC) += reset-qcom-pdc.o
 obj-$(CONFIG_RESET_SIMPLE) += reset-simple.o
 obj-$(CONFIG_RESET_STM32MP157) += reset-stm32mp1.o
+obj-$(CONFIG_RESET_SOCFPGA) += reset-socfpga.o
 obj-$(CONFIG_RESET_SUNXI) += reset-sunxi.o
 obj-$(CONFIG_RESET_TI_SCI) += reset-ti-sci.o
 obj-$(CONFIG_RESET_TI_SYSCON) += reset-ti-syscon.o
 obj-$(CONFIG_RESET_UNIPHIER) += reset-uniphier.o
-obj-$(CONFIG_RESET_UNIPHIER_USB3) += reset-uniphier-usb3.o
+obj-$(CONFIG_RESET_UNIPHIER_GLUE) += reset-uniphier-glue.o
 obj-$(CONFIG_RESET_ZYNQ) += reset-zynq.o
 
index d1887c0..9582efb 100644 (file)
@@ -795,3 +795,45 @@ devm_reset_control_array_get(struct device *dev, bool shared, bool optional)
        return rstc;
 }
 EXPORT_SYMBOL_GPL(devm_reset_control_array_get);
+
+static int reset_control_get_count_from_lookup(struct device *dev)
+{
+       const struct reset_control_lookup *lookup;
+       const char *dev_id;
+       int count = 0;
+
+       if (!dev)
+               return -EINVAL;
+
+       dev_id = dev_name(dev);
+       mutex_lock(&reset_lookup_mutex);
+
+       list_for_each_entry(lookup, &reset_lookup_list, list) {
+               if (!strcmp(lookup->dev_id, dev_id))
+                       count++;
+       }
+
+       mutex_unlock(&reset_lookup_mutex);
+
+       if (count == 0)
+               count = -ENOENT;
+
+       return count;
+}
+
+/**
+ * reset_control_get_count - Count number of resets available with a device
+ *
+ * @dev: device for which to return the number of resets
+ *
+ * Returns positive reset count on success, or error number on failure and
+ * on count being zero.
+ */
+int reset_control_get_count(struct device *dev)
+{
+       if (dev->of_node)
+               return of_reset_control_get_count(dev->of_node);
+
+       return reset_control_get_count_from_lookup(dev);
+}
+EXPORT_SYMBOL_GPL(reset_control_get_count);
index 8bce391..4c7b864 100644 (file)
@@ -86,6 +86,7 @@ static int hsdk_reset_reset(struct reset_controller_dev *rcdev,
 
 static const struct reset_control_ops hsdk_reset_ops = {
        .reset  = hsdk_reset_reset,
+       .deassert = hsdk_reset_reset,
 };
 
 static int hsdk_reset_probe(struct platform_device *pdev)
index a91107f..77fbba3 100644 (file)
@@ -109,7 +109,7 @@ struct reset_simple_devdata {
 #define SOCFPGA_NR_BANKS       8
 
 static const struct reset_simple_devdata reset_simple_socfpga = {
-       .reg_offset = 0x10,
+       .reg_offset = 0x20,
        .nr_resets = SOCFPGA_NR_BANKS * 32,
        .status_active_low = true,
 };
@@ -120,7 +120,8 @@ static const struct reset_simple_devdata reset_simple_active_low = {
 };
 
 static const struct of_device_id reset_simple_dt_ids[] = {
-       { .compatible = "altr,rst-mgr", .data = &reset_simple_socfpga },
+       { .compatible = "altr,stratix10-rst-mgr",
+               .data = &reset_simple_socfpga },
        { .compatible = "st,stm32-rcc", },
        { .compatible = "allwinner,sun6i-a31-clock-reset",
                .data = &reset_simple_active_low },
@@ -166,14 +167,6 @@ static int reset_simple_probe(struct platform_device *pdev)
                data->status_active_low = devdata->status_active_low;
        }
 
-       if (of_device_is_compatible(dev->of_node, "altr,rst-mgr") &&
-           of_property_read_u32(dev->of_node, "altr,modrst-offset",
-                                &reg_offset)) {
-               dev_warn(dev,
-                        "missing altr,modrst-offset property, assuming 0x%x!\n",
-                        reg_offset);
-       }
-
        data->membase += reg_offset;
 
        return devm_reset_controller_register(dev, &data->rcdev);
diff --git a/drivers/reset/reset-socfpga.c b/drivers/reset/reset-socfpga.c
new file mode 100644 (file)
index 0000000..318cfc5
--- /dev/null
@@ -0,0 +1,88 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * Copyright (C) 2018, Intel Corporation
+ * Copied from reset-sunxi.c
+ */
+
+#include <linux/err.h>
+#include <linux/io.h>
+#include <linux/init.h>
+#include <linux/of.h>
+#include <linux/of_address.h>
+#include <linux/platform_device.h>
+#include <linux/reset-controller.h>
+#include <linux/slab.h>
+#include <linux/spinlock.h>
+#include <linux/types.h>
+
+#include "reset-simple.h"
+
+#define SOCFPGA_NR_BANKS       8
+void __init socfpga_reset_init(void);
+
+static int a10_reset_init(struct device_node *np)
+{
+       struct reset_simple_data *data;
+       struct resource res;
+       resource_size_t size;
+       int ret;
+       u32 reg_offset = 0x10;
+
+       data = kzalloc(sizeof(*data), GFP_KERNEL);
+       if (!data)
+               return -ENOMEM;
+
+       ret = of_address_to_resource(np, 0, &res);
+       if (ret)
+               goto err_alloc;
+
+       size = resource_size(&res);
+       if (!request_mem_region(res.start, size, np->name)) {
+               ret = -EBUSY;
+               goto err_alloc;
+       }
+
+       data->membase = ioremap(res.start, size);
+       if (!data->membase) {
+               ret = -ENOMEM;
+               goto err_alloc;
+       }
+
+       if (of_property_read_u32(np, "altr,modrst-offset", &reg_offset))
+               pr_warn("missing altr,modrst-offset property, assuming 0x10\n");
+       data->membase += reg_offset;
+
+       spin_lock_init(&data->lock);
+
+       data->rcdev.owner = THIS_MODULE;
+       data->rcdev.nr_resets = SOCFPGA_NR_BANKS * 32;
+       data->rcdev.ops = &reset_simple_ops;
+       data->rcdev.of_node = np;
+       data->status_active_low = true;
+
+       return reset_controller_register(&data->rcdev);
+
+err_alloc:
+       kfree(data);
+       return ret;
+};
+
+/*
+ * These are the reset controller we need to initialize early on in
+ * our system, before we can even think of using a regular device
+ * driver for it.
+ * The controllers that we can register through the regular device
+ * model are handled by the simple reset driver directly.
+ */
+static const struct of_device_id socfpga_early_reset_dt_ids[] __initconst = {
+       { .compatible = "altr,rst-mgr", },
+       { /* sentinel */ },
+};
+
+void __init socfpga_reset_init(void)
+{
+       struct device_node *np;
+
+       for_each_matching_node(np, socfpga_early_reset_dt_ids)
+               a10_reset_init(np);
+}
diff --git a/drivers/reset/reset-uniphier-glue.c b/drivers/reset/reset-uniphier-glue.c
new file mode 100644 (file)
index 0000000..a45923f
--- /dev/null
@@ -0,0 +1,183 @@
+// SPDX-License-Identifier: GPL-2.0
+//
+// reset-uniphier-glue.c - Glue layer reset driver for UniPhier
+// Copyright 2018 Socionext Inc.
+// Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
+
+#include <linux/clk.h>
+#include <linux/module.h>
+#include <linux/of_device.h>
+#include <linux/platform_device.h>
+#include <linux/reset.h>
+
+#include "reset-simple.h"
+
+#define MAX_CLKS       2
+#define MAX_RSTS       2
+
+struct uniphier_glue_reset_soc_data {
+       int nclks;
+       const char * const *clock_names;
+       int nrsts;
+       const char * const *reset_names;
+};
+
+struct uniphier_glue_reset_priv {
+       struct clk_bulk_data clk[MAX_CLKS];
+       struct reset_control *rst[MAX_RSTS];
+       struct reset_simple_data rdata;
+       const struct uniphier_glue_reset_soc_data *data;
+};
+
+static int uniphier_glue_reset_probe(struct platform_device *pdev)
+{
+       struct device *dev = &pdev->dev;
+       struct uniphier_glue_reset_priv *priv;
+       struct resource *res;
+       resource_size_t size;
+       const char *name;
+       int i, ret, nr;
+
+       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
+       if (!priv)
+               return -ENOMEM;
+
+       priv->data = of_device_get_match_data(dev);
+       if (WARN_ON(!priv->data || priv->data->nclks > MAX_CLKS ||
+                   priv->data->nrsts > MAX_RSTS))
+               return -EINVAL;
+
+       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+       size = resource_size(res);
+       priv->rdata.membase = devm_ioremap_resource(dev, res);
+       if (IS_ERR(priv->rdata.membase))
+               return PTR_ERR(priv->rdata.membase);
+
+       for (i = 0; i < priv->data->nclks; i++)
+               priv->clk[i].id = priv->data->clock_names[i];
+       ret = devm_clk_bulk_get(dev, priv->data->nclks, priv->clk);
+       if (ret)
+               return ret;
+
+       for (i = 0; i < priv->data->nrsts; i++) {
+               name = priv->data->reset_names[i];
+               priv->rst[i] = devm_reset_control_get_shared(dev, name);
+               if (IS_ERR(priv->rst[i]))
+                       return PTR_ERR(priv->rst[i]);
+       }
+
+       ret = clk_bulk_prepare_enable(priv->data->nclks, priv->clk);
+       if (ret)
+               return ret;
+
+       for (nr = 0; nr < priv->data->nrsts; nr++) {
+               ret = reset_control_deassert(priv->rst[nr]);
+               if (ret)
+                       goto out_rst_assert;
+       }
+
+       spin_lock_init(&priv->rdata.lock);
+       priv->rdata.rcdev.owner = THIS_MODULE;
+       priv->rdata.rcdev.nr_resets = size * BITS_PER_BYTE;
+       priv->rdata.rcdev.ops = &reset_simple_ops;
+       priv->rdata.rcdev.of_node = dev->of_node;
+       priv->rdata.active_low = true;
+
+       platform_set_drvdata(pdev, priv);
+
+       ret = devm_reset_controller_register(dev, &priv->rdata.rcdev);
+       if (ret)
+               goto out_rst_assert;
+
+       return 0;
+
+out_rst_assert:
+       while (nr--)
+               reset_control_assert(priv->rst[nr]);
+
+       clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
+
+       return ret;
+}
+
+static int uniphier_glue_reset_remove(struct platform_device *pdev)
+{
+       struct uniphier_glue_reset_priv *priv = platform_get_drvdata(pdev);
+       int i;
+
+       for (i = 0; i < priv->data->nrsts; i++)
+               reset_control_assert(priv->rst[i]);
+
+       clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
+
+       return 0;
+}
+
+static const char * const uniphier_pro4_clock_reset_names[] = {
+       "gio", "link",
+};
+
+static const struct uniphier_glue_reset_soc_data uniphier_pro4_data = {
+       .nclks = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
+       .clock_names = uniphier_pro4_clock_reset_names,
+       .nrsts = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
+       .reset_names = uniphier_pro4_clock_reset_names,
+};
+
+static const char * const uniphier_pxs2_clock_reset_names[] = {
+       "link",
+};
+
+static const struct uniphier_glue_reset_soc_data uniphier_pxs2_data = {
+       .nclks = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
+       .clock_names = uniphier_pxs2_clock_reset_names,
+       .nrsts = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
+       .reset_names = uniphier_pxs2_clock_reset_names,
+};
+
+static const struct of_device_id uniphier_glue_reset_match[] = {
+       {
+               .compatible = "socionext,uniphier-pro4-usb3-reset",
+               .data = &uniphier_pro4_data,
+       },
+       {
+               .compatible = "socionext,uniphier-pxs2-usb3-reset",
+               .data = &uniphier_pxs2_data,
+       },
+       {
+               .compatible = "socionext,uniphier-ld20-usb3-reset",
+               .data = &uniphier_pxs2_data,
+       },
+       {
+               .compatible = "socionext,uniphier-pxs3-usb3-reset",
+               .data = &uniphier_pxs2_data,
+       },
+       {
+               .compatible = "socionext,uniphier-pro4-ahci-reset",
+               .data = &uniphier_pro4_data,
+       },
+       {
+               .compatible = "socionext,uniphier-pxs2-ahci-reset",
+               .data = &uniphier_pxs2_data,
+       },
+       {
+               .compatible = "socionext,uniphier-pxs3-ahci-reset",
+               .data = &uniphier_pxs2_data,
+       },
+       { /* Sentinel */ }
+};
+MODULE_DEVICE_TABLE(of, uniphier_glue_reset_match);
+
+static struct platform_driver uniphier_glue_reset_driver = {
+       .probe = uniphier_glue_reset_probe,
+       .remove = uniphier_glue_reset_remove,
+       .driver = {
+               .name = "uniphier-glue-reset",
+               .of_match_table = uniphier_glue_reset_match,
+       },
+};
+module_platform_driver(uniphier_glue_reset_driver);
+
+MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
+MODULE_DESCRIPTION("UniPhier Glue layer reset driver");
+MODULE_LICENSE("GPL");
diff --git a/drivers/reset/reset-uniphier-usb3.c b/drivers/reset/reset-uniphier-usb3.c
deleted file mode 100644 (file)
index ffa1b19..0000000
+++ /dev/null
@@ -1,171 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-//
-// reset-uniphier-usb3.c - USB3 reset driver for UniPhier
-// Copyright 2018 Socionext Inc.
-// Author: Kunihiko Hayashi <hayashi.kunihiko@socionext.com>
-
-#include <linux/clk.h>
-#include <linux/module.h>
-#include <linux/of_device.h>
-#include <linux/platform_device.h>
-#include <linux/reset.h>
-
-#include "reset-simple.h"
-
-#define MAX_CLKS       2
-#define MAX_RSTS       2
-
-struct uniphier_usb3_reset_soc_data {
-       int nclks;
-       const char * const *clock_names;
-       int nrsts;
-       const char * const *reset_names;
-};
-
-struct uniphier_usb3_reset_priv {
-       struct clk_bulk_data clk[MAX_CLKS];
-       struct reset_control *rst[MAX_RSTS];
-       struct reset_simple_data rdata;
-       const struct uniphier_usb3_reset_soc_data *data;
-};
-
-static int uniphier_usb3_reset_probe(struct platform_device *pdev)
-{
-       struct device *dev = &pdev->dev;
-       struct uniphier_usb3_reset_priv *priv;
-       struct resource *res;
-       resource_size_t size;
-       const char *name;
-       int i, ret, nr;
-
-       priv = devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL);
-       if (!priv)
-               return -ENOMEM;
-
-       priv->data = of_device_get_match_data(dev);
-       if (WARN_ON(!priv->data || priv->data->nclks > MAX_CLKS ||
-                   priv->data->nrsts > MAX_RSTS))
-               return -EINVAL;
-
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       size = resource_size(res);
-       priv->rdata.membase = devm_ioremap_resource(dev, res);
-       if (IS_ERR(priv->rdata.membase))
-               return PTR_ERR(priv->rdata.membase);
-
-       for (i = 0; i < priv->data->nclks; i++)
-               priv->clk[i].id = priv->data->clock_names[i];
-       ret = devm_clk_bulk_get(dev, priv->data->nclks, priv->clk);
-       if (ret)
-               return ret;
-
-       for (i = 0; i < priv->data->nrsts; i++) {
-               name = priv->data->reset_names[i];
-               priv->rst[i] = devm_reset_control_get_shared(dev, name);
-               if (IS_ERR(priv->rst[i]))
-                       return PTR_ERR(priv->rst[i]);
-       }
-
-       ret = clk_bulk_prepare_enable(priv->data->nclks, priv->clk);
-       if (ret)
-               return ret;
-
-       for (nr = 0; nr < priv->data->nrsts; nr++) {
-               ret = reset_control_deassert(priv->rst[nr]);
-               if (ret)
-                       goto out_rst_assert;
-       }
-
-       spin_lock_init(&priv->rdata.lock);
-       priv->rdata.rcdev.owner = THIS_MODULE;
-       priv->rdata.rcdev.nr_resets = size * BITS_PER_BYTE;
-       priv->rdata.rcdev.ops = &reset_simple_ops;
-       priv->rdata.rcdev.of_node = dev->of_node;
-       priv->rdata.active_low = true;
-
-       platform_set_drvdata(pdev, priv);
-
-       ret = devm_reset_controller_register(dev, &priv->rdata.rcdev);
-       if (ret)
-               goto out_rst_assert;
-
-       return 0;
-
-out_rst_assert:
-       while (nr--)
-               reset_control_assert(priv->rst[nr]);
-
-       clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
-
-       return ret;
-}
-
-static int uniphier_usb3_reset_remove(struct platform_device *pdev)
-{
-       struct uniphier_usb3_reset_priv *priv = platform_get_drvdata(pdev);
-       int i;
-
-       for (i = 0; i < priv->data->nrsts; i++)
-               reset_control_assert(priv->rst[i]);
-
-       clk_bulk_disable_unprepare(priv->data->nclks, priv->clk);
-
-       return 0;
-}
-
-static const char * const uniphier_pro4_clock_reset_names[] = {
-       "gio", "link",
-};
-
-static const struct uniphier_usb3_reset_soc_data uniphier_pro4_data = {
-       .nclks = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
-       .clock_names = uniphier_pro4_clock_reset_names,
-       .nrsts = ARRAY_SIZE(uniphier_pro4_clock_reset_names),
-       .reset_names = uniphier_pro4_clock_reset_names,
-};
-
-static const char * const uniphier_pxs2_clock_reset_names[] = {
-       "link",
-};
-
-static const struct uniphier_usb3_reset_soc_data uniphier_pxs2_data = {
-       .nclks = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
-       .clock_names = uniphier_pxs2_clock_reset_names,
-       .nrsts = ARRAY_SIZE(uniphier_pxs2_clock_reset_names),
-       .reset_names = uniphier_pxs2_clock_reset_names,
-};
-
-static const struct of_device_id uniphier_usb3_reset_match[] = {
-       {
-               .compatible = "socionext,uniphier-pro4-usb3-reset",
-               .data = &uniphier_pro4_data,
-       },
-       {
-               .compatible = "socionext,uniphier-pxs2-usb3-reset",
-               .data = &uniphier_pxs2_data,
-       },
-       {
-               .compatible = "socionext,uniphier-ld20-usb3-reset",
-               .data = &uniphier_pxs2_data,
-       },
-       {
-               .compatible = "socionext,uniphier-pxs3-usb3-reset",
-               .data = &uniphier_pxs2_data,
-       },
-       { /* Sentinel */ }
-};
-MODULE_DEVICE_TABLE(of, uniphier_usb3_reset_match);
-
-static struct platform_driver uniphier_usb3_reset_driver = {
-       .probe = uniphier_usb3_reset_probe,
-       .remove = uniphier_usb3_reset_remove,
-       .driver = {
-               .name = "uniphier-usb3-reset",
-               .of_match_table = uniphier_usb3_reset_match,
-       },
-};
-module_platform_driver(uniphier_usb3_reset_driver);
-
-MODULE_AUTHOR("Kunihiko Hayashi <hayashi.kunihiko@socionext.com>");
-MODULE_DESCRIPTION("UniPhier USB3 Reset Driver");
-MODULE_LICENSE("GPL");
index 4e7b55a..6e294b4 100644 (file)
@@ -4469,6 +4469,14 @@ static int dasd_symm_io(struct dasd_device *device, void __user *argp)
                usrparm.psf_data &= 0x7fffffffULL;
                usrparm.rssd_result &= 0x7fffffffULL;
        }
+       /* at least 2 bytes are accessed and should be allocated */
+       if (usrparm.psf_data_len < 2) {
+               DBF_DEV_EVENT(DBF_WARNING, device,
+                             "Symmetrix ioctl invalid data length %d",
+                             usrparm.psf_data_len);
+               rc = -EINVAL;
+               goto out;
+       }
        /* alloc I/O data area */
        psf_data = kzalloc(usrparm.psf_data_len, GFP_KERNEL | GFP_DMA);
        rssd_result = kzalloc(usrparm.rssd_result_len, GFP_KERNEL | GFP_DMA);
index 194ffd5..039b207 100644 (file)
@@ -60,7 +60,9 @@ static void sclp_cpu_capability_notify(struct work_struct *work)
 
 static void __ref sclp_cpu_change_notify(struct work_struct *work)
 {
+       lock_device_hotplug();
        smp_rescan_cpus();
+       unlock_device_hotplug();
 }
 
 static void sclp_conf_receiver_fn(struct evbuf_header *evbuf)
index 48ea000..5a69974 100644 (file)
@@ -248,7 +248,8 @@ static inline int ap_test_config(unsigned int *field, unsigned int nr)
 static inline int ap_test_config_card_id(unsigned int id)
 {
        if (!ap_configuration)  /* QCI not supported */
-               return 1;
+               /* only ids 0...3F may be probed */
+               return id < 0x40 ? 1 : 0;
        return ap_test_config(ap_configuration->apm, id);
 }
 
index dcbf5c8..ed8e58f 100644 (file)
@@ -89,8 +89,8 @@ static int register_sba(struct ism_dev *ism)
        dma_addr_t dma_handle;
        struct ism_sba *sba;
 
-       sba = dma_zalloc_coherent(&ism->pdev->dev, PAGE_SIZE,
-                                 &dma_handle, GFP_KERNEL);
+       sba = dma_alloc_coherent(&ism->pdev->dev, PAGE_SIZE, &dma_handle,
+                                GFP_KERNEL);
        if (!sba)
                return -ENOMEM;
 
@@ -116,8 +116,8 @@ static int register_ieq(struct ism_dev *ism)
        dma_addr_t dma_handle;
        struct ism_eq *ieq;
 
-       ieq = dma_zalloc_coherent(&ism->pdev->dev, PAGE_SIZE,
-                                 &dma_handle, GFP_KERNEL);
+       ieq = dma_alloc_coherent(&ism->pdev->dev, PAGE_SIZE, &dma_handle,
+                                GFP_KERNEL);
        if (!ieq)
                return -ENOMEM;
 
@@ -234,10 +234,9 @@ static int ism_alloc_dmb(struct ism_dev *ism, struct smcd_dmb *dmb)
            test_and_set_bit(dmb->sba_idx, ism->sba_bitmap))
                return -EINVAL;
 
-       dmb->cpu_addr = dma_zalloc_coherent(&ism->pdev->dev, dmb->dmb_len,
-                                           &dmb->dma_addr, GFP_KERNEL |
-                                           __GFP_NOWARN | __GFP_NOMEMALLOC |
-                                           __GFP_COMP | __GFP_NORETRY);
+       dmb->cpu_addr = dma_alloc_coherent(&ism->pdev->dev, dmb->dmb_len,
+                                          &dmb->dma_addr,
+                                          GFP_KERNEL | __GFP_NOWARN | __GFP_NOMEMALLOC | __GFP_COMP | __GFP_NORETRY);
        if (!dmb->cpu_addr)
                clear_bit(dmb->sba_idx, ism->sba_bitmap);
 
index 0ee0269..122059e 100644 (file)
@@ -22,6 +22,7 @@
 #include <linux/hashtable.h>
 #include <linux/ip.h>
 #include <linux/refcount.h>
+#include <linux/workqueue.h>
 
 #include <net/ipv6.h>
 #include <net/if_inet6.h>
@@ -789,6 +790,7 @@ struct qeth_card {
        struct qeth_seqno seqno;
        struct qeth_card_options options;
 
+       struct workqueue_struct *event_wq;
        wait_queue_head_t wait_q;
        spinlock_t mclock;
        unsigned long active_vlans[BITS_TO_LONGS(VLAN_N_VID)];
@@ -962,7 +964,6 @@ extern const struct attribute_group *qeth_osn_attr_groups[];
 extern const struct attribute_group qeth_device_attr_group;
 extern const struct attribute_group qeth_device_blkt_group;
 extern const struct device_type qeth_generic_devtype;
-extern struct workqueue_struct *qeth_wq;
 
 int qeth_card_hw_is_reachable(struct qeth_card *);
 const char *qeth_get_cardname_short(struct qeth_card *);
index e63e031..89f9122 100644 (file)
@@ -74,8 +74,7 @@ static void qeth_notify_skbs(struct qeth_qdio_out_q *queue,
 static void qeth_release_skbs(struct qeth_qdio_out_buffer *buf);
 static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *, int);
 
-struct workqueue_struct *qeth_wq;
-EXPORT_SYMBOL_GPL(qeth_wq);
+static struct workqueue_struct *qeth_wq;
 
 int qeth_card_hw_is_reachable(struct qeth_card *card)
 {
@@ -566,6 +565,7 @@ static int __qeth_issue_next_read(struct qeth_card *card)
                QETH_DBF_MESSAGE(2, "error %i on device %x when starting next read ccw!\n",
                                 rc, CARD_DEVID(card));
                atomic_set(&channel->irq_pending, 0);
+               qeth_release_buffer(channel, iob);
                card->read_or_write_problem = 1;
                qeth_schedule_recovery(card);
                wake_up(&card->wait_q);
@@ -1127,6 +1127,8 @@ static void qeth_irq(struct ccw_device *cdev, unsigned long intparm,
                rc = qeth_get_problem(card, cdev, irb);
                if (rc) {
                        card->read_or_write_problem = 1;
+                       if (iob)
+                               qeth_release_buffer(iob->channel, iob);
                        qeth_clear_ipacmd_list(card);
                        qeth_schedule_recovery(card);
                        goto out;
@@ -1466,6 +1468,10 @@ static struct qeth_card *qeth_alloc_card(struct ccwgroup_device *gdev)
        CARD_RDEV(card) = gdev->cdev[0];
        CARD_WDEV(card) = gdev->cdev[1];
        CARD_DDEV(card) = gdev->cdev[2];
+
+       card->event_wq = alloc_ordered_workqueue("%s", 0, dev_name(&gdev->dev));
+       if (!card->event_wq)
+               goto out_wq;
        if (qeth_setup_channel(&card->read, true))
                goto out_ip;
        if (qeth_setup_channel(&card->write, true))
@@ -1481,6 +1487,8 @@ out_data:
 out_channel:
        qeth_clean_channel(&card->read);
 out_ip:
+       destroy_workqueue(card->event_wq);
+out_wq:
        dev_set_drvdata(&gdev->dev, NULL);
        kfree(card);
 out:
@@ -1809,6 +1817,7 @@ static int qeth_idx_activate_get_answer(struct qeth_card *card,
                QETH_DBF_MESSAGE(2, "Error2 in activating channel rc=%d\n", rc);
                QETH_DBF_TEXT_(SETUP, 2, "2err%d", rc);
                atomic_set(&channel->irq_pending, 0);
+               qeth_release_buffer(channel, iob);
                wake_up(&card->wait_q);
                return rc;
        }
@@ -1878,6 +1887,7 @@ static int qeth_idx_activate_channel(struct qeth_card *card,
                        rc);
                QETH_DBF_TEXT_(SETUP, 2, "1err%d", rc);
                atomic_set(&channel->irq_pending, 0);
+               qeth_release_buffer(channel, iob);
                wake_up(&card->wait_q);
                return rc;
        }
@@ -2058,6 +2068,7 @@ int qeth_send_control_data(struct qeth_card *card, int len,
        }
        reply = qeth_alloc_reply(card);
        if (!reply) {
+               qeth_release_buffer(channel, iob);
                return -ENOMEM;
        }
        reply->callback = reply_cb;
@@ -2389,11 +2400,12 @@ static int qeth_init_qdio_out_buf(struct qeth_qdio_out_q *q, int bidx)
        return 0;
 }
 
-static void qeth_free_qdio_out_buf(struct qeth_qdio_out_q *q)
+static void qeth_free_output_queue(struct qeth_qdio_out_q *q)
 {
        if (!q)
                return;
 
+       qeth_clear_outq_buffers(q, 1);
        qdio_free_buffers(q->qdio_bufs, QDIO_MAX_BUFFERS_PER_Q);
        kfree(q);
 }
@@ -2467,10 +2479,8 @@ out_freeoutqbufs:
                card->qdio.out_qs[i]->bufs[j] = NULL;
        }
 out_freeoutq:
-       while (i > 0) {
-               qeth_free_qdio_out_buf(card->qdio.out_qs[--i]);
-               qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
-       }
+       while (i > 0)
+               qeth_free_output_queue(card->qdio.out_qs[--i]);
        kfree(card->qdio.out_qs);
        card->qdio.out_qs = NULL;
 out_freepool:
@@ -2503,10 +2513,8 @@ static void qeth_free_qdio_buffers(struct qeth_card *card)
        qeth_free_buffer_pool(card);
        /* free outbound qdio_qs */
        if (card->qdio.out_qs) {
-               for (i = 0; i < card->qdio.no_out_queues; ++i) {
-                       qeth_clear_outq_buffers(card->qdio.out_qs[i], 1);
-                       qeth_free_qdio_out_buf(card->qdio.out_qs[i]);
-               }
+               for (i = 0; i < card->qdio.no_out_queues; i++)
+                       qeth_free_output_queue(card->qdio.out_qs[i]);
                kfree(card->qdio.out_qs);
                card->qdio.out_qs = NULL;
        }
@@ -5028,6 +5036,7 @@ static void qeth_core_free_card(struct qeth_card *card)
        qeth_clean_channel(&card->read);
        qeth_clean_channel(&card->write);
        qeth_clean_channel(&card->data);
+       destroy_workqueue(card->event_wq);
        qeth_free_qdio_buffers(card);
        unregister_service_level(&card->qeth_service_level);
        dev_set_drvdata(&card->gdev->dev, NULL);
index f108d4b..a43de2f 100644 (file)
@@ -369,6 +369,8 @@ static void qeth_l2_stop_card(struct qeth_card *card, int recovery_mode)
                qeth_clear_cmd_buffers(&card->read);
                qeth_clear_cmd_buffers(&card->write);
        }
+
+       flush_workqueue(card->event_wq);
 }
 
 static int qeth_l2_process_inbound_buffer(struct qeth_card *card,
@@ -801,6 +803,8 @@ static void qeth_l2_remove_device(struct ccwgroup_device *cgdev)
 
        if (cgdev->state == CCWGROUP_ONLINE)
                qeth_l2_set_offline(cgdev);
+
+       cancel_work_sync(&card->close_dev_work);
        if (qeth_netdev_is_registered(card->dev))
                unregister_netdev(card->dev);
 }
@@ -1434,7 +1438,7 @@ static void qeth_bridge_state_change(struct qeth_card *card,
        data->card = card;
        memcpy(&data->qports, qports,
                        sizeof(struct qeth_sbp_state_change) + extrasize);
-       queue_work(qeth_wq, &data->worker);
+       queue_work(card->event_wq, &data->worker);
 }
 
 struct qeth_bridge_host_data {
@@ -1506,7 +1510,7 @@ static void qeth_bridge_host_event(struct qeth_card *card,
        data->card = card;
        memcpy(&data->hostevs, hostevs,
                        sizeof(struct qeth_ipacmd_addr_change) + extrasize);
-       queue_work(qeth_wq, &data->worker);
+       queue_work(card->event_wq, &data->worker);
 }
 
 /* SETBRIDGEPORT support; sending commands */
index 42a7cdc..df34bff 100644 (file)
@@ -1433,6 +1433,8 @@ static void qeth_l3_stop_card(struct qeth_card *card, int recovery_mode)
                qeth_clear_cmd_buffers(&card->read);
                qeth_clear_cmd_buffers(&card->write);
        }
+
+       flush_workqueue(card->event_wq);
 }
 
 /*
@@ -2338,6 +2340,7 @@ static void qeth_l3_remove_device(struct ccwgroup_device *cgdev)
        if (cgdev->state == CCWGROUP_ONLINE)
                qeth_l3_set_offline(cgdev);
 
+       cancel_work_sync(&card->close_dev_work);
        if (qeth_netdev_is_registered(card->dev))
                unregister_netdev(card->dev);
        qeth_l3_clear_ip_htable(card, 0);
index 9cf30d1..e390f8c 100644 (file)
@@ -403,7 +403,6 @@ struct zfcp_adapter *zfcp_adapter_enqueue(struct ccw_device *ccw_device)
                goto failed;
 
        /* report size limit per scatter-gather segment */
-       adapter->dma_parms.max_segment_size = ZFCP_QDIO_SBALE_LEN;
        adapter->ccw_device->dev.dma_parms = &adapter->dma_parms;
 
        adapter->stat_read_buf_num = FSF_STATUS_READS_RECOM;
index 00acc71..f4f6a07 100644 (file)
@@ -428,6 +428,8 @@ static struct scsi_host_template zfcp_scsi_host_template = {
        .max_sectors             = (((QDIO_MAX_ELEMENTS_PER_BUFFER - 1)
                                     * ZFCP_QDIO_MAX_SBALS_PER_REQ) - 2) * 8,
                                   /* GCD, adjusted later */
+       /* report size limit per scatter-gather segment */
+       .max_segment_size        = ZFCP_QDIO_SBALE_LEN,
        .dma_boundary            = ZFCP_QDIO_SBALE_LEN - 1,
        .shost_attrs             = zfcp_sysfs_shost_attrs,
        .sdev_attrs              = zfcp_sysfs_sdev_attrs,
index fc9dbad..ae1d56d 100644 (file)
@@ -635,7 +635,7 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 {
        struct virtio_ccw_device *vcdev = to_vc_device(vdev);
        unsigned long *indicatorp = NULL;
-       int ret, i;
+       int ret, i, queue_idx = 0;
        struct ccw1 *ccw;
 
        ccw = kzalloc(sizeof(*ccw), GFP_DMA | GFP_KERNEL);
@@ -643,8 +643,14 @@ static int virtio_ccw_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                return -ENOMEM;
 
        for (i = 0; i < nvqs; ++i) {
-               vqs[i] = virtio_ccw_setup_vq(vdev, i, callbacks[i], names[i],
-                                            ctx ? ctx[i] : false, ccw);
+               if (!names[i]) {
+                       vqs[i] = NULL;
+                       continue;
+               }
+
+               vqs[i] = virtio_ccw_setup_vq(vdev, queue_idx++, callbacks[i],
+                                            names[i], ctx ? ctx[i] : false,
+                                            ccw);
                if (IS_ERR(vqs[i])) {
                        ret = PTR_ERR(vqs[i]);
                        vqs[i] = NULL;
index e8f5f7c..cd09610 100644 (file)
@@ -646,8 +646,9 @@ static int twl_allocate_memory(TW_Device_Extension *tw_dev, int size, int which)
        unsigned long *cpu_addr;
        int retval = 1;
 
-       cpu_addr = dma_zalloc_coherent(&tw_dev->tw_pci_dev->dev,
-                       size * TW_Q_LENGTH, &dma_handle, GFP_KERNEL);
+       cpu_addr = dma_alloc_coherent(&tw_dev->tw_pci_dev->dev,
+                                     size * TW_Q_LENGTH, &dma_handle,
+                                     GFP_KERNEL);
        if (!cpu_addr) {
                TW_PRINTK(tw_dev->host, TW_DRIVER, 0x5, "Memory allocation failed");
                goto out;
index 128d658..16957d7 100644 (file)
@@ -295,7 +295,7 @@ NCR_700_detect(struct scsi_host_template *tpnt,
        if(tpnt->sdev_attrs == NULL)
                tpnt->sdev_attrs = NCR_700_dev_attrs;
 
-       memory = dma_alloc_attrs(hostdata->dev, TOTAL_MEM_SIZE, &pScript,
+       memory = dma_alloc_attrs(dev, TOTAL_MEM_SIZE, &pScript,
                                 GFP_KERNEL, DMA_ATTR_NON_CONSISTENT);
        if(memory == NULL) {
                printk(KERN_ERR "53c700: Failed to allocate memory for driver, detaching\n");
index ff53fd0..66c5143 100644 (file)
@@ -1123,8 +1123,8 @@ static int inia100_probe_one(struct pci_dev *pdev,
 
        /* Get total memory needed for SCB */
        sz = ORC_MAXQUEUE * sizeof(struct orc_scb);
-       host->scb_virt = dma_zalloc_coherent(&pdev->dev, sz, &host->scb_phys,
-                                            GFP_KERNEL);
+       host->scb_virt = dma_alloc_coherent(&pdev->dev, sz, &host->scb_phys,
+                                           GFP_KERNEL);
        if (!host->scb_virt) {
                printk("inia100: SCB memory allocation error\n");
                goto out_host_put;
@@ -1132,8 +1132,8 @@ static int inia100_probe_one(struct pci_dev *pdev,
 
        /* Get total memory needed for ESCB */
        sz = ORC_MAXQUEUE * sizeof(struct orc_extended_scb);
-       host->escb_virt = dma_zalloc_coherent(&pdev->dev, sz, &host->escb_phys,
-                                             GFP_KERNEL);
+       host->escb_virt = dma_alloc_coherent(&pdev->dev, sz, &host->escb_phys,
+                                            GFP_KERNEL);
        if (!host->escb_virt) {
                printk("inia100: ESCB memory allocation error\n");
                goto out_free_scb_array;
index 634ddb9..7e56a11 100644 (file)
@@ -1747,11 +1747,10 @@ static int aac_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
                shost->max_sectors = (shost->sg_tablesize * 8) + 112;
        }
 
-       error = dma_set_max_seg_size(&pdev->dev,
-               (aac->adapter_info.options & AAC_OPT_NEW_COMM) ?
-                       (shost->max_sectors << 9) : 65536);
-       if (error)
-               goto out_deinit;
+       if (aac->adapter_info.options & AAC_OPT_NEW_COMM)
+               shost->max_segment_size = shost->max_sectors << 9;
+       else
+               shost->max_segment_size = 65536;
 
        /*
         * Firmware printf works only with older firmware.
index f83f79b..07efcb9 100644 (file)
@@ -280,7 +280,7 @@ static ssize_t asd_show_dev_rev(struct device *dev,
        return snprintf(buf, PAGE_SIZE, "%s\n",
                        asd_dev_rev[asd_ha->revision_id]);
 }
-static DEVICE_ATTR(revision, S_IRUGO, asd_show_dev_rev, NULL);
+static DEVICE_ATTR(aic_revision, S_IRUGO, asd_show_dev_rev, NULL);
 
 static ssize_t asd_show_dev_bios_build(struct device *dev,
                                       struct device_attribute *attr,char *buf)
@@ -477,7 +477,7 @@ static int asd_create_dev_attrs(struct asd_ha_struct *asd_ha)
 {
        int err;
 
-       err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+       err = device_create_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
        if (err)
                return err;
 
@@ -499,13 +499,13 @@ err_update_bios:
 err_biosb:
        device_remove_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
 err_rev:
-       device_remove_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+       device_remove_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
        return err;
 }
 
 static void asd_remove_dev_attrs(struct asd_ha_struct *asd_ha)
 {
-       device_remove_file(&asd_ha->pcidev->dev, &dev_attr_revision);
+       device_remove_file(&asd_ha->pcidev->dev, &dev_attr_aic_revision);
        device_remove_file(&asd_ha->pcidev->dev, &dev_attr_bios_build);
        device_remove_file(&asd_ha->pcidev->dev, &dev_attr_pcba_sn);
        device_remove_file(&asd_ha->pcidev->dev, &dev_attr_update_bios);
index 0f6751b..57c6fa3 100644 (file)
@@ -587,8 +587,10 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb)
        case ACB_ADAPTER_TYPE_B: {
                struct MessageUnit_B *reg;
                acb->roundup_ccbsize = roundup(sizeof(struct MessageUnit_B), 32);
-               dma_coherent = dma_zalloc_coherent(&pdev->dev, acb->roundup_ccbsize,
-                       &dma_coherent_handle, GFP_KERNEL);
+               dma_coherent = dma_alloc_coherent(&pdev->dev,
+                                                 acb->roundup_ccbsize,
+                                                 &dma_coherent_handle,
+                                                 GFP_KERNEL);
                if (!dma_coherent) {
                        pr_notice("arcmsr%d: DMA allocation failed\n", acb->host->host_no);
                        return false;
@@ -617,8 +619,10 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb)
                struct MessageUnit_D *reg;
 
                acb->roundup_ccbsize = roundup(sizeof(struct MessageUnit_D), 32);
-               dma_coherent = dma_zalloc_coherent(&pdev->dev, acb->roundup_ccbsize,
-                       &dma_coherent_handle, GFP_KERNEL);
+               dma_coherent = dma_alloc_coherent(&pdev->dev,
+                                                 acb->roundup_ccbsize,
+                                                 &dma_coherent_handle,
+                                                 GFP_KERNEL);
                if (!dma_coherent) {
                        pr_notice("arcmsr%d: DMA allocation failed\n", acb->host->host_no);
                        return false;
@@ -659,8 +663,10 @@ static bool arcmsr_alloc_io_queue(struct AdapterControlBlock *acb)
                uint32_t completeQ_size;
                completeQ_size = sizeof(struct deliver_completeQ) * ARCMSR_MAX_HBE_DONEQUEUE + 128;
                acb->roundup_ccbsize = roundup(completeQ_size, 32);
-               dma_coherent = dma_zalloc_coherent(&pdev->dev, acb->roundup_ccbsize,
-                       &dma_coherent_handle, GFP_KERNEL);
+               dma_coherent = dma_alloc_coherent(&pdev->dev,
+                                                 acb->roundup_ccbsize,
+                                                 &dma_coherent_handle,
+                                                 GFP_KERNEL);
                if (!dma_coherent){
                        pr_notice("arcmsr%d: DMA allocation failed\n", acb->host->host_no);
                        return false;
index 39f3820..74e2600 100644 (file)
@@ -3321,8 +3321,8 @@ static int be_queue_alloc(struct beiscsi_hba *phba, struct be_queue_info *q,
        q->len = len;
        q->entry_size = entry_size;
        mem->size = len * entry_size;
-       mem->va = dma_zalloc_coherent(&phba->pcidev->dev, mem->size, &mem->dma,
-                       GFP_KERNEL);
+       mem->va = dma_alloc_coherent(&phba->pcidev->dev, mem->size, &mem->dma,
+                                    GFP_KERNEL);
        if (!mem->va)
                return -ENOMEM;
        return 0;
index ca7b7bb..d4febaa 100644 (file)
@@ -293,8 +293,8 @@ static int beiscsi_prep_nemb_cmd(struct beiscsi_hba *phba,
                                 struct be_dma_mem *cmd,
                                 u8 subsystem, u8 opcode, u32 size)
 {
-       cmd->va = dma_zalloc_coherent(&phba->ctrl.pdev->dev, size, &cmd->dma,
-                       GFP_KERNEL);
+       cmd->va = dma_alloc_coherent(&phba->ctrl.pdev->dev, size, &cmd->dma,
+                                    GFP_KERNEL);
        if (!cmd->va) {
                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_CONFIG,
                            "BG_%d : Failed to allocate memory for if info\n");
@@ -1510,10 +1510,9 @@ int beiscsi_mgmt_invalidate_icds(struct beiscsi_hba *phba,
                return -EINVAL;
 
        nonemb_cmd.size = sizeof(union be_invldt_cmds_params);
-       nonemb_cmd.va = dma_zalloc_coherent(&phba->ctrl.pdev->dev,
-                                             nonemb_cmd.size,
-                                             &nonemb_cmd.dma,
-                                             GFP_KERNEL);
+       nonemb_cmd.va = dma_alloc_coherent(&phba->ctrl.pdev->dev,
+                                          nonemb_cmd.size, &nonemb_cmd.dma,
+                                          GFP_KERNEL);
        if (!nonemb_cmd.va) {
                beiscsi_log(phba, KERN_ERR, BEISCSI_LOG_EH,
                            "BM_%d : invldt_cmds_params alloc failed\n");
index 5d163ca..d8e6d74 100644 (file)
@@ -3264,9 +3264,9 @@ bfad_fcxp_map_sg(struct bfad_s *bfad, void *payload_kbuf,
        /* Allocate dma coherent memory */
        buf_info = buf_base;
        buf_info->size = payload_len;
-       buf_info->virt = dma_zalloc_coherent(&bfad->pcidev->dev,
-                                            buf_info->size, &buf_info->phys,
-                                            GFP_KERNEL);
+       buf_info->virt = dma_alloc_coherent(&bfad->pcidev->dev,
+                                           buf_info->size, &buf_info->phys,
+                                           GFP_KERNEL);
        if (!buf_info->virt)
                goto out_free_mem;
 
index e8ae4d6..039328d 100644 (file)
@@ -1857,10 +1857,10 @@ int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba)
         * entries. Hence the limit with one page is 8192 task context
         * entries.
         */
-       hba->task_ctx_bd_tbl = dma_zalloc_coherent(&hba->pcidev->dev,
-                                                  PAGE_SIZE,
-                                                  &hba->task_ctx_bd_dma,
-                                                  GFP_KERNEL);
+       hba->task_ctx_bd_tbl = dma_alloc_coherent(&hba->pcidev->dev,
+                                                 PAGE_SIZE,
+                                                 &hba->task_ctx_bd_dma,
+                                                 GFP_KERNEL);
        if (!hba->task_ctx_bd_tbl) {
                printk(KERN_ERR PFX "unable to allocate task context BDT\n");
                rc = -1;
@@ -1894,10 +1894,10 @@ int bnx2fc_setup_task_ctx(struct bnx2fc_hba *hba)
        task_ctx_bdt = (struct regpair *)hba->task_ctx_bd_tbl;
        for (i = 0; i < task_ctx_arr_sz; i++) {
 
-               hba->task_ctx[i] = dma_zalloc_coherent(&hba->pcidev->dev,
-                                                      PAGE_SIZE,
-                                                      &hba->task_ctx_dma[i],
-                                                      GFP_KERNEL);
+               hba->task_ctx[i] = dma_alloc_coherent(&hba->pcidev->dev,
+                                                     PAGE_SIZE,
+                                                     &hba->task_ctx_dma[i],
+                                                     GFP_KERNEL);
                if (!hba->task_ctx[i]) {
                        printk(KERN_ERR PFX "unable to alloc task context\n");
                        rc = -1;
@@ -2031,19 +2031,19 @@ static int bnx2fc_allocate_hash_table(struct bnx2fc_hba *hba)
        }
 
        for (i = 0; i < segment_count; ++i) {
-               hba->hash_tbl_segments[i] = dma_zalloc_coherent(&hba->pcidev->dev,
-                                                               BNX2FC_HASH_TBL_CHUNK_SIZE,
-                                                               &dma_segment_array[i],
-                                                               GFP_KERNEL);
+               hba->hash_tbl_segments[i] = dma_alloc_coherent(&hba->pcidev->dev,
+                                                              BNX2FC_HASH_TBL_CHUNK_SIZE,
+                                                              &dma_segment_array[i],
+                                                              GFP_KERNEL);
                if (!hba->hash_tbl_segments[i]) {
                        printk(KERN_ERR PFX "hash segment alloc failed\n");
                        goto cleanup_dma;
                }
        }
 
-       hba->hash_tbl_pbl = dma_zalloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
-                                               &hba->hash_tbl_pbl_dma,
-                                               GFP_KERNEL);
+       hba->hash_tbl_pbl = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+                                              &hba->hash_tbl_pbl_dma,
+                                              GFP_KERNEL);
        if (!hba->hash_tbl_pbl) {
                printk(KERN_ERR PFX "hash table pbl alloc failed\n");
                goto cleanup_dma;
@@ -2104,10 +2104,9 @@ int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba)
                return -ENOMEM;
 
        mem_size = BNX2FC_NUM_MAX_SESS * sizeof(struct regpair);
-       hba->t2_hash_tbl_ptr = dma_zalloc_coherent(&hba->pcidev->dev,
-                                                  mem_size,
-                                                  &hba->t2_hash_tbl_ptr_dma,
-                                                  GFP_KERNEL);
+       hba->t2_hash_tbl_ptr = dma_alloc_coherent(&hba->pcidev->dev, mem_size,
+                                                 &hba->t2_hash_tbl_ptr_dma,
+                                                 GFP_KERNEL);
        if (!hba->t2_hash_tbl_ptr) {
                printk(KERN_ERR PFX "unable to allocate t2 hash table ptr\n");
                bnx2fc_free_fw_resc(hba);
@@ -2116,9 +2115,9 @@ int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba)
 
        mem_size = BNX2FC_NUM_MAX_SESS *
                                sizeof(struct fcoe_t2_hash_table_entry);
-       hba->t2_hash_tbl = dma_zalloc_coherent(&hba->pcidev->dev, mem_size,
-                                              &hba->t2_hash_tbl_dma,
-                                              GFP_KERNEL);
+       hba->t2_hash_tbl = dma_alloc_coherent(&hba->pcidev->dev, mem_size,
+                                             &hba->t2_hash_tbl_dma,
+                                             GFP_KERNEL);
        if (!hba->t2_hash_tbl) {
                printk(KERN_ERR PFX "unable to allocate t2 hash table\n");
                bnx2fc_free_fw_resc(hba);
@@ -2140,9 +2139,9 @@ int bnx2fc_setup_fw_resc(struct bnx2fc_hba *hba)
                return -ENOMEM;
        }
 
-       hba->stats_buffer = dma_zalloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
-                                               &hba->stats_buf_dma,
-                                               GFP_KERNEL);
+       hba->stats_buffer = dma_alloc_coherent(&hba->pcidev->dev, PAGE_SIZE,
+                                              &hba->stats_buf_dma,
+                                              GFP_KERNEL);
        if (!hba->stats_buffer) {
                printk(KERN_ERR PFX "unable to alloc Stats Buffer\n");
                bnx2fc_free_fw_resc(hba);
index 350257c..bc9f2a2 100644 (file)
@@ -240,6 +240,7 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba)
                return NULL;
        }
 
+       cmgr->hba = hba;
        cmgr->free_list = kcalloc(arr_sz, sizeof(*cmgr->free_list),
                                  GFP_KERNEL);
        if (!cmgr->free_list) {
@@ -256,7 +257,6 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba)
                goto mem_err;
        }
 
-       cmgr->hba = hba;
        cmgr->cmds = (struct bnx2fc_cmd **)(cmgr + 1);
 
        for (i = 0; i < arr_sz; i++)  {
@@ -295,7 +295,7 @@ struct bnx2fc_cmd_mgr *bnx2fc_cmd_mgr_alloc(struct bnx2fc_hba *hba)
 
        /* Allocate pool of io_bdts - one for each bnx2fc_cmd */
        mem_size = num_ios * sizeof(struct io_bdt *);
-       cmgr->io_bdt_pool = kmalloc(mem_size, GFP_KERNEL);
+       cmgr->io_bdt_pool = kzalloc(mem_size, GFP_KERNEL);
        if (!cmgr->io_bdt_pool) {
                printk(KERN_ERR PFX "failed to alloc io_bdt_pool\n");
                goto mem_err;
index e3d1c7c..d735e87 100644 (file)
@@ -672,8 +672,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->sq_mem_size = (tgt->sq_mem_size + (CNIC_PAGE_SIZE - 1)) &
                           CNIC_PAGE_MASK;
 
-       tgt->sq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
-                                     &tgt->sq_dma, GFP_KERNEL);
+       tgt->sq = dma_alloc_coherent(&hba->pcidev->dev, tgt->sq_mem_size,
+                                    &tgt->sq_dma, GFP_KERNEL);
        if (!tgt->sq) {
                printk(KERN_ERR PFX "unable to allocate SQ memory %d\n",
                        tgt->sq_mem_size);
@@ -685,8 +685,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->cq_mem_size = (tgt->cq_mem_size + (CNIC_PAGE_SIZE - 1)) &
                           CNIC_PAGE_MASK;
 
-       tgt->cq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
-                                     &tgt->cq_dma, GFP_KERNEL);
+       tgt->cq = dma_alloc_coherent(&hba->pcidev->dev, tgt->cq_mem_size,
+                                    &tgt->cq_dma, GFP_KERNEL);
        if (!tgt->cq) {
                printk(KERN_ERR PFX "unable to allocate CQ memory %d\n",
                        tgt->cq_mem_size);
@@ -698,8 +698,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->rq_mem_size = (tgt->rq_mem_size + (CNIC_PAGE_SIZE - 1)) &
                           CNIC_PAGE_MASK;
 
-       tgt->rq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->rq_mem_size,
-                                     &tgt->rq_dma, GFP_KERNEL);
+       tgt->rq = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_mem_size,
+                                    &tgt->rq_dma, GFP_KERNEL);
        if (!tgt->rq) {
                printk(KERN_ERR PFX "unable to allocate RQ memory %d\n",
                        tgt->rq_mem_size);
@@ -710,8 +710,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->rq_pbl_size = (tgt->rq_pbl_size + (CNIC_PAGE_SIZE - 1)) &
                           CNIC_PAGE_MASK;
 
-       tgt->rq_pbl = dma_zalloc_coherent(&hba->pcidev->dev, tgt->rq_pbl_size,
-                                         &tgt->rq_pbl_dma, GFP_KERNEL);
+       tgt->rq_pbl = dma_alloc_coherent(&hba->pcidev->dev, tgt->rq_pbl_size,
+                                        &tgt->rq_pbl_dma, GFP_KERNEL);
        if (!tgt->rq_pbl) {
                printk(KERN_ERR PFX "unable to allocate RQ PBL %d\n",
                        tgt->rq_pbl_size);
@@ -735,9 +735,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->xferq_mem_size = (tgt->xferq_mem_size + (CNIC_PAGE_SIZE - 1)) &
                               CNIC_PAGE_MASK;
 
-       tgt->xferq = dma_zalloc_coherent(&hba->pcidev->dev,
-                                        tgt->xferq_mem_size, &tgt->xferq_dma,
-                                        GFP_KERNEL);
+       tgt->xferq = dma_alloc_coherent(&hba->pcidev->dev,
+                                       tgt->xferq_mem_size, &tgt->xferq_dma,
+                                       GFP_KERNEL);
        if (!tgt->xferq) {
                printk(KERN_ERR PFX "unable to allocate XFERQ %d\n",
                        tgt->xferq_mem_size);
@@ -749,9 +749,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->confq_mem_size = (tgt->confq_mem_size + (CNIC_PAGE_SIZE - 1)) &
                               CNIC_PAGE_MASK;
 
-       tgt->confq = dma_zalloc_coherent(&hba->pcidev->dev,
-                                        tgt->confq_mem_size, &tgt->confq_dma,
-                                        GFP_KERNEL);
+       tgt->confq = dma_alloc_coherent(&hba->pcidev->dev,
+                                       tgt->confq_mem_size, &tgt->confq_dma,
+                                       GFP_KERNEL);
        if (!tgt->confq) {
                printk(KERN_ERR PFX "unable to allocate CONFQ %d\n",
                        tgt->confq_mem_size);
@@ -763,9 +763,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->confq_pbl_size =
                (tgt->confq_pbl_size + (CNIC_PAGE_SIZE - 1)) & CNIC_PAGE_MASK;
 
-       tgt->confq_pbl = dma_zalloc_coherent(&hba->pcidev->dev,
-                                            tgt->confq_pbl_size,
-                                            &tgt->confq_pbl_dma, GFP_KERNEL);
+       tgt->confq_pbl = dma_alloc_coherent(&hba->pcidev->dev,
+                                           tgt->confq_pbl_size,
+                                           &tgt->confq_pbl_dma, GFP_KERNEL);
        if (!tgt->confq_pbl) {
                printk(KERN_ERR PFX "unable to allocate CONFQ PBL %d\n",
                        tgt->confq_pbl_size);
@@ -787,9 +787,9 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        /* Allocate and map ConnDB */
        tgt->conn_db_mem_size = sizeof(struct fcoe_conn_db);
 
-       tgt->conn_db = dma_zalloc_coherent(&hba->pcidev->dev,
-                                          tgt->conn_db_mem_size,
-                                          &tgt->conn_db_dma, GFP_KERNEL);
+       tgt->conn_db = dma_alloc_coherent(&hba->pcidev->dev,
+                                         tgt->conn_db_mem_size,
+                                         &tgt->conn_db_dma, GFP_KERNEL);
        if (!tgt->conn_db) {
                printk(KERN_ERR PFX "unable to allocate conn_db %d\n",
                                                tgt->conn_db_mem_size);
@@ -802,8 +802,8 @@ static int bnx2fc_alloc_session_resc(struct bnx2fc_hba *hba,
        tgt->lcq_mem_size = (tgt->lcq_mem_size + (CNIC_PAGE_SIZE - 1)) &
                             CNIC_PAGE_MASK;
 
-       tgt->lcq = dma_zalloc_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
-                                      &tgt->lcq_dma, GFP_KERNEL);
+       tgt->lcq = dma_alloc_coherent(&hba->pcidev->dev, tgt->lcq_mem_size,
+                                     &tgt->lcq_dma, GFP_KERNEL);
 
        if (!tgt->lcq) {
                printk(KERN_ERR PFX "unable to allocate lcq %d\n",
index 91f5316..fae6f71 100644 (file)
@@ -1070,8 +1070,8 @@ int bnx2i_alloc_qp_resc(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
 
        /* Allocate memory area for actual SQ element */
        ep->qp.sq_virt =
-               dma_zalloc_coherent(&hba->pcidev->dev, ep->qp.sq_mem_size,
-                                       &ep->qp.sq_phys, GFP_KERNEL);
+               dma_alloc_coherent(&hba->pcidev->dev, ep->qp.sq_mem_size,
+                                  &ep->qp.sq_phys, GFP_KERNEL);
        if (!ep->qp.sq_virt) {
                printk(KERN_ALERT "bnx2i: unable to alloc SQ BD memory %d\n",
                                  ep->qp.sq_mem_size);
@@ -1106,8 +1106,8 @@ int bnx2i_alloc_qp_resc(struct bnx2i_hba *hba, struct bnx2i_endpoint *ep)
 
        /* Allocate memory area for actual CQ element */
        ep->qp.cq_virt =
-               dma_zalloc_coherent(&hba->pcidev->dev, ep->qp.cq_mem_size,
-                                       &ep->qp.cq_phys, GFP_KERNEL);
+               dma_alloc_coherent(&hba->pcidev->dev, ep->qp.cq_mem_size,
+                                  &ep->qp.cq_phys, GFP_KERNEL);
        if (!ep->qp.cq_virt) {
                printk(KERN_ALERT "bnx2i: unable to alloc CQ BD memory %d\n",
                                  ep->qp.cq_mem_size);
index 8a00403..9bd2bd8 100644 (file)
@@ -594,12 +594,12 @@ csio_vport_create(struct fc_vport *fc_vport, bool disable)
        }
 
        fc_vport_set_state(fc_vport, FC_VPORT_INITIALIZING);
+       ln->fc_vport = fc_vport;
 
        if (csio_fcoe_alloc_vnp(hw, ln))
                goto error;
 
        *(struct csio_lnode **)fc_vport->dd_data = ln;
-       ln->fc_vport = fc_vport;
        if (!fc_vport->node_name)
                fc_vport->node_name = wwn_to_u64(csio_ln_wwnn(ln));
        if (!fc_vport->port_name)
index dc12933..66bbd21 100644 (file)
@@ -233,8 +233,8 @@ csio_wr_alloc_q(struct csio_hw *hw, uint32_t qsize, uint32_t wrsize,
 
        q = wrm->q_arr[free_idx];
 
-       q->vstart = dma_zalloc_coherent(&hw->pdev->dev, qsz, &q->pstart,
-                       GFP_KERNEL);
+       q->vstart = dma_alloc_coherent(&hw->pdev->dev, qsz, &q->pstart,
+                                      GFP_KERNEL);
        if (!q->vstart) {
                csio_err(hw,
                         "Failed to allocate DMA memory for "
index 8a20411..75e1273 100644 (file)
@@ -1144,7 +1144,7 @@ static void ddp_clear_map(struct cxgbi_device *cdev, struct cxgbi_ppm *ppm,
 }
 
 static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
-                                      unsigned int tid, int pg_idx, bool reply)
+                               unsigned int tid, int pg_idx)
 {
        struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
                                        GFP_KERNEL);
@@ -1160,7 +1160,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
        req = (struct cpl_set_tcb_field *)skb->head;
        req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
        OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
-       req->reply = V_NO_REPLY(reply ? 0 : 1);
+       req->reply = V_NO_REPLY(1);
        req->cpu_idx = 0;
        req->word = htons(31);
        req->mask = cpu_to_be64(0xF0000000);
@@ -1177,11 +1177,10 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk,
  * @tid: connection id
  * @hcrc: header digest enabled
  * @dcrc: data digest enabled
- * @reply: request reply from h/w
  * set up the iscsi digest settings for a connection identified by tid
  */
 static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
-                            int hcrc, int dcrc, int reply)
+                                int hcrc, int dcrc)
 {
        struct sk_buff *skb = alloc_wr(sizeof(struct cpl_set_tcb_field), 0,
                                        GFP_KERNEL);
@@ -1197,7 +1196,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
        req = (struct cpl_set_tcb_field *)skb->head;
        req->wr.wr_hi = htonl(V_WR_OP(FW_WROPCODE_FORWARD));
        OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
-       req->reply = V_NO_REPLY(reply ? 0 : 1);
+       req->reply = V_NO_REPLY(1);
        req->cpu_idx = 0;
        req->word = htons(31);
        req->mask = cpu_to_be64(0x0F000000);
index 49f8028..d26f50a 100644 (file)
@@ -1548,16 +1548,22 @@ static void do_set_tcb_rpl(struct cxgbi_device *cdev, struct sk_buff *skb)
        struct cxgbi_sock *csk;
 
        csk = lookup_tid(t, tid);
-       if (!csk)
+       if (!csk) {
                pr_err("can't find conn. for tid %u.\n", tid);
+               return;
+       }
 
        log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
                "csk 0x%p,%u,%lx,%u, status 0x%x.\n",
                csk, csk->state, csk->flags, csk->tid, rpl->status);
 
-       if (rpl->status != CPL_ERR_NONE)
+       if (rpl->status != CPL_ERR_NONE) {
                pr_err("csk 0x%p,%u, SET_TCB_RPL status %u.\n",
                        csk, tid, rpl->status);
+               csk->err = -EINVAL;
+       }
+
+       complete(&csk->cmpl);
 
        __kfree_skb(skb);
 }
@@ -1983,7 +1989,7 @@ static int ddp_set_map(struct cxgbi_ppm *ppm, struct cxgbi_sock *csk,
 }
 
 static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
-                               int pg_idx, bool reply)
+                               int pg_idx)
 {
        struct sk_buff *skb;
        struct cpl_set_tcb_field *req;
@@ -1999,7 +2005,7 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
        req = (struct cpl_set_tcb_field *)skb->head;
        INIT_TP_WR(req, csk->tid);
        OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, csk->tid));
-       req->reply_ctrl = htons(NO_REPLY_V(reply) | QUEUENO_V(csk->rss_qid));
+       req->reply_ctrl = htons(NO_REPLY_V(0) | QUEUENO_V(csk->rss_qid));
        req->word_cookie = htons(0);
        req->mask = cpu_to_be64(0x3 << 8);
        req->val = cpu_to_be64(pg_idx << 8);
@@ -2008,12 +2014,15 @@ static int ddp_setup_conn_pgidx(struct cxgbi_sock *csk, unsigned int tid,
        log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
                "csk 0x%p, tid 0x%x, pg_idx %u.\n", csk, csk->tid, pg_idx);
 
+       reinit_completion(&csk->cmpl);
        cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
-       return 0;
+       wait_for_completion(&csk->cmpl);
+
+       return csk->err;
 }
 
 static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
-                                int hcrc, int dcrc, int reply)
+                                int hcrc, int dcrc)
 {
        struct sk_buff *skb;
        struct cpl_set_tcb_field *req;
@@ -2031,7 +2040,7 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
        req = (struct cpl_set_tcb_field *)skb->head;
        INIT_TP_WR(req, tid);
        OPCODE_TID(req) = htonl(MK_OPCODE_TID(CPL_SET_TCB_FIELD, tid));
-       req->reply_ctrl = htons(NO_REPLY_V(reply) | QUEUENO_V(csk->rss_qid));
+       req->reply_ctrl = htons(NO_REPLY_V(0) | QUEUENO_V(csk->rss_qid));
        req->word_cookie = htons(0);
        req->mask = cpu_to_be64(0x3 << 4);
        req->val = cpu_to_be64(((hcrc ? ULP_CRC_HEADER : 0) |
@@ -2041,8 +2050,11 @@ static int ddp_setup_conn_digest(struct cxgbi_sock *csk, unsigned int tid,
        log_debug(1 << CXGBI_DBG_TOE | 1 << CXGBI_DBG_SOCK,
                "csk 0x%p, tid 0x%x, crc %d,%d.\n", csk, csk->tid, hcrc, dcrc);
 
+       reinit_completion(&csk->cmpl);
        cxgb4_ofld_send(csk->cdev->ports[csk->port_id], skb);
-       return 0;
+       wait_for_completion(&csk->cmpl);
+
+       return csk->err;
 }
 
 static struct cxgbi_ppm *cdev2ppm(struct cxgbi_device *cdev)
index 75f8764..2457425 100644 (file)
@@ -573,6 +573,7 @@ static struct cxgbi_sock *cxgbi_sock_create(struct cxgbi_device *cdev)
        skb_queue_head_init(&csk->receive_queue);
        skb_queue_head_init(&csk->write_queue);
        timer_setup(&csk->retry_timer, NULL, 0);
+       init_completion(&csk->cmpl);
        rwlock_init(&csk->callback_lock);
        csk->cdev = cdev;
        csk->flags = 0;
@@ -2251,14 +2252,14 @@ int cxgbi_set_conn_param(struct iscsi_cls_conn *cls_conn,
                if (!err && conn->hdrdgst_en)
                        err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
                                                        conn->hdrdgst_en,
-                                                       conn->datadgst_en, 0);
+                                                       conn->datadgst_en);
                break;
        case ISCSI_PARAM_DATADGST_EN:
                err = iscsi_set_param(cls_conn, param, buf, buflen);
                if (!err && conn->datadgst_en)
                        err = csk->cdev->csk_ddp_setup_digest(csk, csk->tid,
                                                        conn->hdrdgst_en,
-                                                       conn->datadgst_en, 0);
+                                                       conn->datadgst_en);
                break;
        case ISCSI_PARAM_MAX_R2T:
                return iscsi_tcp_set_max_r2t(conn, buf);
@@ -2384,7 +2385,7 @@ int cxgbi_bind_conn(struct iscsi_cls_session *cls_session,
 
        ppm = csk->cdev->cdev2ppm(csk->cdev);
        err = csk->cdev->csk_ddp_setup_pgidx(csk, csk->tid,
-                                            ppm->tformat.pgsz_idx_dflt, 0);
+                                            ppm->tformat.pgsz_idx_dflt);
        if (err < 0)
                return err;
 
index 5d5d8b5..1917ff5 100644 (file)
@@ -149,6 +149,7 @@ struct cxgbi_sock {
        struct sk_buff_head receive_queue;
        struct sk_buff_head write_queue;
        struct timer_list retry_timer;
+       struct completion cmpl;
        int err;
        rwlock_t callback_lock;
        void *user_data;
@@ -490,9 +491,9 @@ struct cxgbi_device {
                                  struct cxgbi_ppm *,
                                  struct cxgbi_task_tag_info *);
        int (*csk_ddp_setup_digest)(struct cxgbi_sock *,
-                               unsigned int, int, int, int);
+                                   unsigned int, int, int);
        int (*csk_ddp_setup_pgidx)(struct cxgbi_sock *,
-                               unsigned int, int, bool);
+                                  unsigned int, int);
 
        void (*csk_release_offload_resources)(struct cxgbi_sock *);
        int (*csk_rx_pdu_ready)(struct cxgbi_sock *, struct sk_buff *);
index bfa13e3..c8bad2c 100644 (file)
@@ -3687,6 +3687,7 @@ static int cxlflash_probe(struct pci_dev *pdev,
        host->max_cmd_len = CXLFLASH_MAX_CDB_LEN;
 
        cfg = shost_priv(host);
+       cfg->state = STATE_PROBING;
        cfg->host = host;
        rc = alloc_mem(cfg);
        if (rc) {
@@ -3775,6 +3776,7 @@ out:
        return rc;
 
 out_remove:
+       cfg->state = STATE_PROBED;
        cxlflash_remove(pdev);
        goto out;
 }
index e2420a8..c92b382 100644 (file)
@@ -2507,6 +2507,12 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                sha->sas_port[i] = &hisi_hba->port[i].sas_port;
        }
 
+       if (hisi_hba->prot_mask) {
+               dev_info(dev, "Registering for DIF/DIX prot_mask=0x%x\n",
+                        prot_mask);
+               scsi_host_set_prot(hisi_hba->shost, prot_mask);
+       }
+
        rc = scsi_add_host(shost, dev);
        if (rc)
                goto err_out_ha;
@@ -2519,12 +2525,6 @@ hisi_sas_v3_probe(struct pci_dev *pdev, const struct pci_device_id *id)
        if (rc)
                goto err_out_register_ha;
 
-       if (hisi_hba->prot_mask) {
-               dev_info(dev, "Registering for DIF/DIX prot_mask=0x%x\n",
-                        prot_mask);
-               scsi_host_set_prot(hisi_hba->shost, prot_mask);
-       }
-
        scsi_scan_host(shost);
 
        return 0;
index 68b90c4..1727d0c 100644 (file)
@@ -576,6 +576,13 @@ static struct isci_host *isci_host_alloc(struct pci_dev *pdev, int id)
        shost->max_lun = ~0;
        shost->max_cmd_len = MAX_COMMAND_SIZE;
 
+       /* turn on DIF support */
+       scsi_host_set_prot(shost,
+                          SHOST_DIF_TYPE1_PROTECTION |
+                          SHOST_DIF_TYPE2_PROTECTION |
+                          SHOST_DIF_TYPE3_PROTECTION);
+       scsi_host_set_guard(shost, SHOST_DIX_GUARD_CRC);
+
        err = scsi_add_host(shost, &pdev->dev);
        if (err)
                goto err_shost;
@@ -663,13 +670,6 @@ static int isci_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id)
                        goto err_host_alloc;
                }
                pci_info->hosts[i] = h;
-
-               /* turn on DIF support */
-               scsi_host_set_prot(to_shost(h),
-                                  SHOST_DIF_TYPE1_PROTECTION |
-                                  SHOST_DIF_TYPE2_PROTECTION |
-                                  SHOST_DIF_TYPE3_PROTECTION);
-               scsi_host_set_guard(to_shost(h), SHOST_DIX_GUARD_CRC);
        }
 
        err = isci_setup_interrupts(pdev);
index be83590..ff943f4 100644 (file)
@@ -1726,14 +1726,14 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
            fc_frame_payload_op(fp) != ELS_LS_ACC) {
                FC_LPORT_DBG(lport, "FLOGI not accepted or bad response\n");
                fc_lport_error(lport, fp);
-               goto err;
+               goto out;
        }
 
        flp = fc_frame_payload_get(fp, sizeof(*flp));
        if (!flp) {
                FC_LPORT_DBG(lport, "FLOGI bad response\n");
                fc_lport_error(lport, fp);
-               goto err;
+               goto out;
        }
 
        mfs = ntohs(flp->fl_csp.sp_bb_data) &
@@ -1743,7 +1743,7 @@ void fc_lport_flogi_resp(struct fc_seq *sp, struct fc_frame *fp,
                FC_LPORT_DBG(lport, "FLOGI bad mfs:%hu response, "
                             "lport->mfs:%hu\n", mfs, lport->mfs);
                fc_lport_error(lport, fp);
-               goto err;
+               goto out;
        }
 
        if (mfs <= lport->mfs) {
index 9192a1d..dfba492 100644 (file)
@@ -184,7 +184,6 @@ void fc_rport_destroy(struct kref *kref)
        struct fc_rport_priv *rdata;
 
        rdata = container_of(kref, struct fc_rport_priv, kref);
-       WARN_ON(!list_empty(&rdata->peers));
        kfree_rcu(rdata, rcu);
 }
 EXPORT_SYMBOL(fc_rport_destroy);
index b8d325c..120fc52 100644 (file)
@@ -1459,7 +1459,13 @@ static int iscsi_xmit_task(struct iscsi_conn *conn)
        if (test_bit(ISCSI_SUSPEND_BIT, &conn->suspend_tx))
                return -ENODATA;
 
+       spin_lock_bh(&conn->session->back_lock);
+       if (conn->task == NULL) {
+               spin_unlock_bh(&conn->session->back_lock);
+               return -ENODATA;
+       }
        __iscsi_get_task(task);
+       spin_unlock_bh(&conn->session->back_lock);
        spin_unlock_bh(&conn->session->frwd_lock);
        rc = conn->session->tt->xmit_task(task);
        spin_lock_bh(&conn->session->frwd_lock);
index 17eb418..f21c93b 100644 (file)
@@ -828,6 +828,7 @@ static struct domain_device *sas_ex_discover_end_dev(
                rphy = sas_end_device_alloc(phy->port);
                if (!rphy)
                        goto out_free;
+               rphy->identify.phy_identifier = phy_id;
 
                child->rphy = rphy;
                get_device(&rphy->dev);
@@ -854,6 +855,7 @@ static struct domain_device *sas_ex_discover_end_dev(
 
                child->rphy = rphy;
                get_device(&rphy->dev);
+               rphy->identify.phy_identifier = phy_id;
                sas_fill_in_rphy(child, rphy);
 
                list_add_tail(&child->disco_list_node, &parent->port->disco_list);
index 8698af8..2dc564e 100644 (file)
@@ -2730,8 +2730,8 @@ lpfc_bsg_dma_page_alloc(struct lpfc_hba *phba)
        INIT_LIST_HEAD(&dmabuf->list);
 
        /* now, allocate dma buffer */
-       dmabuf->virt = dma_zalloc_coherent(&pcidev->dev, BSG_MBOX_SIZE,
-                                          &(dmabuf->phys), GFP_KERNEL);
+       dmabuf->virt = dma_alloc_coherent(&pcidev->dev, BSG_MBOX_SIZE,
+                                         &(dmabuf->phys), GFP_KERNEL);
 
        if (!dmabuf->virt) {
                kfree(dmabuf);
index c1c3681..bede11e 100644 (file)
@@ -6973,9 +6973,9 @@ lpfc_sli4_create_rpi_hdr(struct lpfc_hba *phba)
        if (!dmabuf)
                return NULL;
 
-       dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev,
-                                          LPFC_HDR_TEMPLATE_SIZE,
-                                          &dmabuf->phys, GFP_KERNEL);
+       dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev,
+                                         LPFC_HDR_TEMPLATE_SIZE,
+                                         &dmabuf->phys, GFP_KERNEL);
        if (!dmabuf->virt) {
                rpi_hdr = NULL;
                goto err_free_dmabuf;
@@ -7397,8 +7397,8 @@ lpfc_sli_pci_mem_setup(struct lpfc_hba *phba)
        }
 
        /* Allocate memory for SLI-2 structures */
-       phba->slim2p.virt = dma_zalloc_coherent(&pdev->dev, SLI2_SLIM_SIZE,
-                                               &phba->slim2p.phys, GFP_KERNEL);
+       phba->slim2p.virt = dma_alloc_coherent(&pdev->dev, SLI2_SLIM_SIZE,
+                                              &phba->slim2p.phys, GFP_KERNEL);
        if (!phba->slim2p.virt)
                goto out_iounmap;
 
@@ -7816,8 +7816,8 @@ lpfc_create_bootstrap_mbox(struct lpfc_hba *phba)
         * plus an alignment restriction of 16 bytes.
         */
        bmbx_size = sizeof(struct lpfc_bmbx_create) + (LPFC_ALIGN_16_BYTE - 1);
-       dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev, bmbx_size,
-                                          &dmabuf->phys, GFP_KERNEL);
+       dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev, bmbx_size,
+                                         &dmabuf->phys, GFP_KERNEL);
        if (!dmabuf->virt) {
                kfree(dmabuf);
                return -ENOMEM;
index f6a5083..4d3b943 100644 (file)
@@ -1827,9 +1827,9 @@ lpfc_sli4_config(struct lpfc_hba *phba, struct lpfcMboxq *mbox,
                 * page, this is used as a priori size of SLI4_PAGE_SIZE for
                 * the later DMA memory free.
                 */
-               viraddr = dma_zalloc_coherent(&phba->pcidev->dev,
-                                             SLI4_PAGE_SIZE, &phyaddr,
-                                             GFP_KERNEL);
+               viraddr = dma_alloc_coherent(&phba->pcidev->dev,
+                                            SLI4_PAGE_SIZE, &phyaddr,
+                                            GFP_KERNEL);
                /* In case of malloc fails, proceed with whatever we have */
                if (!viraddr)
                        break;
index 4c66b19..8c9f790 100644 (file)
@@ -297,7 +297,8 @@ lpfc_nvme_localport_delete(struct nvme_fc_local_port *localport)
                         lport);
 
        /* release any threads waiting for the unreg to complete */
-       complete(&lport->lport_unreg_done);
+       if (lport->vport->localport)
+               complete(lport->lport_unreg_cmp);
 }
 
 /* lpfc_nvme_remoteport_delete
@@ -2545,7 +2546,8 @@ lpfc_nvme_create_localport(struct lpfc_vport *vport)
  */
 void
 lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport,
-                          struct lpfc_nvme_lport *lport)
+                          struct lpfc_nvme_lport *lport,
+                          struct completion *lport_unreg_cmp)
 {
 #if (IS_ENABLED(CONFIG_NVME_FC))
        u32 wait_tmo;
@@ -2557,8 +2559,7 @@ lpfc_nvme_lport_unreg_wait(struct lpfc_vport *vport,
         */
        wait_tmo = msecs_to_jiffies(LPFC_NVME_WAIT_TMO * 1000);
        while (true) {
-               ret = wait_for_completion_timeout(&lport->lport_unreg_done,
-                                                 wait_tmo);
+               ret = wait_for_completion_timeout(lport_unreg_cmp, wait_tmo);
                if (unlikely(!ret)) {
                        lpfc_printf_vlog(vport, KERN_ERR, LOG_NVME_IOERR,
                                         "6176 Lport %p Localport %p wait "
@@ -2592,12 +2593,12 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
        struct lpfc_nvme_lport *lport;
        struct lpfc_nvme_ctrl_stat *cstat;
        int ret;
+       DECLARE_COMPLETION_ONSTACK(lport_unreg_cmp);
 
        if (vport->nvmei_support == 0)
                return;
 
        localport = vport->localport;
-       vport->localport = NULL;
        lport = (struct lpfc_nvme_lport *)localport->private;
        cstat = lport->cstat;
 
@@ -2608,13 +2609,14 @@ lpfc_nvme_destroy_localport(struct lpfc_vport *vport)
        /* lport's rport list is clear.  Unregister
         * lport and release resources.
         */
-       init_completion(&lport->lport_unreg_done);
+       lport->lport_unreg_cmp = &lport_unreg_cmp;
        ret = nvme_fc_unregister_localport(localport);
 
        /* Wait for completion.  This either blocks
         * indefinitely or succeeds
         */
-       lpfc_nvme_lport_unreg_wait(vport, lport);
+       lpfc_nvme_lport_unreg_wait(vport, lport, &lport_unreg_cmp);
+       vport->localport = NULL;
        kfree(cstat);
 
        /* Regardless of the unregister upcall response, clear
index cfd4719..b234d02 100644 (file)
@@ -50,7 +50,7 @@ struct lpfc_nvme_ctrl_stat {
 /* Declare nvme-based local and remote port definitions. */
 struct lpfc_nvme_lport {
        struct lpfc_vport *vport;
-       struct completion lport_unreg_done;
+       struct completion *lport_unreg_cmp;
        /* Add stats counters here */
        struct lpfc_nvme_ctrl_stat *cstat;
        atomic_t fc4NvmeLsRequests;
index 6245f44..95fee83 100644 (file)
@@ -1003,7 +1003,8 @@ lpfc_nvmet_targetport_delete(struct nvmet_fc_target_port *targetport)
        struct lpfc_nvmet_tgtport *tport = targetport->private;
 
        /* release any threads waiting for the unreg to complete */
-       complete(&tport->tport_unreg_done);
+       if (tport->phba->targetport)
+               complete(tport->tport_unreg_cmp);
 }
 
 static void
@@ -1692,6 +1693,7 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
        struct lpfc_nvmet_tgtport *tgtp;
        struct lpfc_queue *wq;
        uint32_t qidx;
+       DECLARE_COMPLETION_ONSTACK(tport_unreg_cmp);
 
        if (phba->nvmet_support == 0)
                return;
@@ -1701,9 +1703,9 @@ lpfc_nvmet_destroy_targetport(struct lpfc_hba *phba)
                        wq = phba->sli4_hba.nvme_wq[qidx];
                        lpfc_nvmet_wqfull_flush(phba, wq, NULL);
                }
-               init_completion(&tgtp->tport_unreg_done);
+               tgtp->tport_unreg_cmp = &tport_unreg_cmp;
                nvmet_fc_unregister_targetport(phba->targetport);
-               wait_for_completion_timeout(&tgtp->tport_unreg_done, 5);
+               wait_for_completion_timeout(&tport_unreg_cmp, 5);
                lpfc_nvmet_cleanup_io_context(phba);
        }
        phba->targetport = NULL;
index 1aaff63..0ec1082 100644 (file)
@@ -34,7 +34,7 @@
 /* Used for NVME Target */
 struct lpfc_nvmet_tgtport {
        struct lpfc_hba *phba;
-       struct completion tport_unreg_done;
+       struct completion *tport_unreg_cmp;
 
        /* Stats counters - lpfc_nvmet_unsol_ls_buffer */
        atomic_t rcv_ls_req_in;
index 30734ca..2242e9b 100644 (file)
@@ -5362,8 +5362,8 @@ lpfc_sli4_read_rev(struct lpfc_hba *phba, LPFC_MBOXQ_t *mboxq,
         * mailbox command.
         */
        dma_size = *vpd_size;
-       dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev, dma_size,
-                                          &dmabuf->phys, GFP_KERNEL);
+       dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev, dma_size,
+                                         &dmabuf->phys, GFP_KERNEL);
        if (!dmabuf->virt) {
                kfree(dmabuf);
                return -ENOMEM;
@@ -6300,10 +6300,9 @@ lpfc_sli4_ras_dma_alloc(struct lpfc_hba *phba,
                        goto free_mem;
                }
 
-               dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev,
+               dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev,
                                                  LPFC_RAS_MAX_ENTRY_SIZE,
-                                                 &dmabuf->phys,
-                                                 GFP_KERNEL);
+                                                 &dmabuf->phys, GFP_KERNEL);
                if (!dmabuf->virt) {
                        kfree(dmabuf);
                        rc = -ENOMEM;
@@ -9408,6 +9407,7 @@ lpfc_sli4_iocb2wqe(struct lpfc_hba *phba, struct lpfc_iocbq *iocbq,
                cmnd = CMD_XMIT_SEQUENCE64_CR;
                if (phba->link_flag & LS_LOOPBACK_MODE)
                        bf_set(wqe_xo, &wqe->xmit_sequence.wge_ctl, 1);
+               /* fall through */
        case CMD_XMIT_SEQUENCE64_CR:
                /* word3 iocb=io_tag32 wqe=reserved */
                wqe->xmit_sequence.rsvd3 = 0;
@@ -13529,6 +13529,7 @@ lpfc_sli4_sp_handle_rcqe(struct lpfc_hba *phba, struct lpfc_rcqe *rcqe)
        case FC_STATUS_RQ_BUF_LEN_EXCEEDED:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                "2537 Receive Frame Truncated!!\n");
+               /* fall through */
        case FC_STATUS_RQ_SUCCESS:
                spin_lock_irqsave(&phba->hbalock, iflags);
                lpfc_sli4_rq_release(hrq, drq);
@@ -13938,7 +13939,7 @@ lpfc_sli4_nvmet_handle_rcqe(struct lpfc_hba *phba, struct lpfc_queue *cq,
        case FC_STATUS_RQ_BUF_LEN_EXCEEDED:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                "6126 Receive Frame Truncated!!\n");
-               /* Drop thru */
+               /* fall through */
        case FC_STATUS_RQ_SUCCESS:
                spin_lock_irqsave(&phba->hbalock, iflags);
                lpfc_sli4_rq_release(hrq, drq);
@@ -14613,9 +14614,9 @@ lpfc_sli4_queue_alloc(struct lpfc_hba *phba, uint32_t page_size,
                dmabuf = kzalloc(sizeof(struct lpfc_dmabuf), GFP_KERNEL);
                if (!dmabuf)
                        goto out_fail;
-               dmabuf->virt = dma_zalloc_coherent(&phba->pcidev->dev,
-                                                  hw_page_size, &dmabuf->phys,
-                                                  GFP_KERNEL);
+               dmabuf->virt = dma_alloc_coherent(&phba->pcidev->dev,
+                                                 hw_page_size, &dmabuf->phys,
+                                                 GFP_KERNEL);
                if (!dmabuf->virt) {
                        kfree(dmabuf);
                        goto out_fail;
@@ -14850,7 +14851,7 @@ lpfc_eq_create(struct lpfc_hba *phba, struct lpfc_queue *eq, uint32_t imax)
                                eq->entry_count);
                if (eq->entry_count < 256)
                        return -EINVAL;
-               /* otherwise default to smallest count (drop through) */
+               /* fall through - otherwise default to smallest count */
        case 256:
                bf_set(lpfc_eq_context_count, &eq_create->u.request.context,
                       LPFC_EQ_CNT_256);
@@ -14981,7 +14982,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
                               LPFC_CQ_CNT_WORD7);
                        break;
                }
-               /* Fall Thru */
+               /* fall through */
        default:
                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                "0361 Unsupported CQ count: "
@@ -14992,7 +14993,7 @@ lpfc_cq_create(struct lpfc_hba *phba, struct lpfc_queue *cq,
                        status = -EINVAL;
                        goto out;
                }
-               /* otherwise default to smallest count (drop through) */
+               /* fall through - otherwise default to smallest count */
        case 256:
                bf_set(lpfc_cq_context_count, &cq_create->u.request.context,
                       LPFC_CQ_CNT_256);
@@ -15152,7 +15153,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp,
                                               LPFC_CQ_CNT_WORD7);
                                        break;
                                }
-                               /* Fall Thru */
+                               /* fall through */
                        default:
                                lpfc_printf_log(phba, KERN_ERR, LOG_SLI,
                                                "3118 Bad CQ count. (%d)\n",
@@ -15161,7 +15162,7 @@ lpfc_cq_create_set(struct lpfc_hba *phba, struct lpfc_queue **cqp,
                                        status = -EINVAL;
                                        goto out;
                                }
-                               /* otherwise default to smallest (drop thru) */
+                               /* fall through - otherwise default to smallest */
                        case 256:
                                bf_set(lpfc_mbx_cq_create_set_cqe_cnt,
                                       &cq_set->u.request, LPFC_CQ_CNT_256);
@@ -15433,7 +15434,7 @@ lpfc_mq_create(struct lpfc_hba *phba, struct lpfc_queue *mq,
                        status = -EINVAL;
                        goto out;
                }
-               /* otherwise default to smallest count (drop through) */
+               /* fall through - otherwise default to smallest count */
        case 16:
                bf_set(lpfc_mq_context_ring_size,
                       &mq_create_ext->u.request.context,
@@ -15852,7 +15853,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
                                status = -EINVAL;
                                goto out;
                        }
-                       /* otherwise default to smallest count (drop through) */
+                       /* fall through - otherwise default to smallest count */
                case 512:
                        bf_set(lpfc_rq_context_rqe_count,
                               &rq_create->u.request.context,
@@ -15989,7 +15990,7 @@ lpfc_rq_create(struct lpfc_hba *phba, struct lpfc_queue *hrq,
                                status = -EINVAL;
                                goto out;
                        }
-                       /* otherwise default to smallest count (drop through) */
+                       /* fall through - otherwise default to smallest count */
                case 512:
                        bf_set(lpfc_rq_context_rqe_count,
                               &rq_create->u.request.context,
index e836392..f112458 100644 (file)
@@ -967,9 +967,10 @@ megaraid_alloc_cmd_packets(adapter_t *adapter)
         * Allocate the common 16-byte aligned memory for the handshake
         * mailbox.
         */
-       raid_dev->una_mbox64 = dma_zalloc_coherent(&adapter->pdev->dev,
-                       sizeof(mbox64_t), &raid_dev->una_mbox64_dma,
-                       GFP_KERNEL);
+       raid_dev->una_mbox64 = dma_alloc_coherent(&adapter->pdev->dev,
+                                                 sizeof(mbox64_t),
+                                                 &raid_dev->una_mbox64_dma,
+                                                 GFP_KERNEL);
 
        if (!raid_dev->una_mbox64) {
                con_log(CL_ANN, (KERN_WARNING
@@ -995,8 +996,8 @@ megaraid_alloc_cmd_packets(adapter_t *adapter)
                        align;
 
        // Allocate memory for commands issued internally
-       adapter->ibuf = dma_zalloc_coherent(&pdev->dev, MBOX_IBUF_SIZE,
-                       &adapter->ibuf_dma_h, GFP_KERNEL);
+       adapter->ibuf = dma_alloc_coherent(&pdev->dev, MBOX_IBUF_SIZE,
+                                          &adapter->ibuf_dma_h, GFP_KERNEL);
        if (!adapter->ibuf) {
 
                con_log(CL_ANN, (KERN_WARNING
@@ -2897,8 +2898,8 @@ megaraid_mbox_product_info(adapter_t *adapter)
         * Issue an ENQUIRY3 command to find out certain adapter parameters,
         * e.g., max channels, max commands etc.
         */
-       pinfo = dma_zalloc_coherent(&adapter->pdev->dev, sizeof(mraid_pinfo_t),
-                       &pinfo_dma_h, GFP_KERNEL);
+       pinfo = dma_alloc_coherent(&adapter->pdev->dev, sizeof(mraid_pinfo_t),
+                                  &pinfo_dma_h, GFP_KERNEL);
        if (pinfo == NULL) {
                con_log(CL_ANN, (KERN_WARNING
                        "megaraid: out of memory, %s %d\n", __func__,
index f7bdd78..fcbff83 100644 (file)
@@ -2273,9 +2273,9 @@ static int megasas_get_ld_vf_affiliation_111(struct megasas_instance *instance,
                               sizeof(struct MR_LD_VF_AFFILIATION_111));
        else {
                new_affiliation_111 =
-                       dma_zalloc_coherent(&instance->pdev->dev,
-                                             sizeof(struct MR_LD_VF_AFFILIATION_111),
-                                             &new_affiliation_111_h, GFP_KERNEL);
+                       dma_alloc_coherent(&instance->pdev->dev,
+                                          sizeof(struct MR_LD_VF_AFFILIATION_111),
+                                          &new_affiliation_111_h, GFP_KERNEL);
                if (!new_affiliation_111) {
                        dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate "
                               "memory for new affiliation for scsi%d\n",
@@ -2380,10 +2380,9 @@ static int megasas_get_ld_vf_affiliation_12(struct megasas_instance *instance,
                       sizeof(struct MR_LD_VF_AFFILIATION));
        else {
                new_affiliation =
-                       dma_zalloc_coherent(&instance->pdev->dev,
-                                             (MAX_LOGICAL_DRIVES + 1) *
-                                             sizeof(struct MR_LD_VF_AFFILIATION),
-                                             &new_affiliation_h, GFP_KERNEL);
+                       dma_alloc_coherent(&instance->pdev->dev,
+                                          (MAX_LOGICAL_DRIVES + 1) * sizeof(struct MR_LD_VF_AFFILIATION),
+                                          &new_affiliation_h, GFP_KERNEL);
                if (!new_affiliation) {
                        dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate "
                               "memory for new affiliation for scsi%d\n",
@@ -2546,9 +2545,10 @@ int megasas_sriov_start_heartbeat(struct megasas_instance *instance,
 
        if (initial) {
                instance->hb_host_mem =
-                       dma_zalloc_coherent(&instance->pdev->dev,
-                                             sizeof(struct MR_CTRL_HB_HOST_MEM),
-                                             &instance->hb_host_mem_h, GFP_KERNEL);
+                       dma_alloc_coherent(&instance->pdev->dev,
+                                          sizeof(struct MR_CTRL_HB_HOST_MEM),
+                                          &instance->hb_host_mem_h,
+                                          GFP_KERNEL);
                if (!instance->hb_host_mem) {
                        dev_printk(KERN_DEBUG, &instance->pdev->dev, "SR-IOV: Couldn't allocate"
                               " memory for heartbeat host memory for scsi%d\n",
@@ -5816,9 +5816,9 @@ megasas_get_seq_num(struct megasas_instance *instance,
        }
 
        dcmd = &cmd->frame->dcmd;
-       el_info = dma_zalloc_coherent(&instance->pdev->dev,
-                       sizeof(struct megasas_evt_log_info), &el_info_h,
-                       GFP_KERNEL);
+       el_info = dma_alloc_coherent(&instance->pdev->dev,
+                                    sizeof(struct megasas_evt_log_info),
+                                    &el_info_h, GFP_KERNEL);
        if (!el_info) {
                megasas_return_cmd(instance, cmd);
                return -ENOMEM;
@@ -6236,7 +6236,7 @@ megasas_set_dma_mask(struct megasas_instance *instance)
                instance->consistent_mask_64bit = true;
 
        dev_info(&pdev->dev, "%s bit DMA mask and %s bit consistent mask\n",
-                ((*pdev->dev.dma_mask == DMA_BIT_MASK(64)) ? "63" : "32"),
+                ((*pdev->dev.dma_mask == DMA_BIT_MASK(63)) ? "63" : "32"),
                 (instance->consistent_mask_64bit ? "63" : "32"));
 
        return 0;
index 211c17c..647f48a 100644 (file)
@@ -175,7 +175,8 @@ megasas_clear_intr_fusion(struct megasas_instance *instance)
        /*
         * Check if it is our interrupt
         */
-       status = readl(&regs->outbound_intr_status);
+       status = megasas_readl(instance,
+                              &regs->outbound_intr_status);
 
        if (status & 1) {
                writel(status, &regs->outbound_intr_status);
@@ -689,8 +690,9 @@ megasas_alloc_rdpq_fusion(struct megasas_instance *instance)
        array_size = sizeof(struct MPI2_IOC_INIT_RDPQ_ARRAY_ENTRY) *
                     MAX_MSIX_QUEUES_FUSION;
 
-       fusion->rdpq_virt = dma_zalloc_coherent(&instance->pdev->dev,
-                       array_size, &fusion->rdpq_phys, GFP_KERNEL);
+       fusion->rdpq_virt = dma_alloc_coherent(&instance->pdev->dev,
+                                              array_size, &fusion->rdpq_phys,
+                                              GFP_KERNEL);
        if (!fusion->rdpq_virt) {
                dev_err(&instance->pdev->dev,
                        "Failed from %s %d\n",  __func__, __LINE__);
index f3e182e..c9dc774 100644 (file)
@@ -1915,8 +1915,9 @@ static int mesh_probe(struct macio_dev *mdev, const struct of_device_id *match)
        /* We use the PCI APIs for now until the generic one gets fixed
         * enough or until we get some macio-specific versions
         */
-       dma_cmd_space = dma_zalloc_coherent(&macio_get_pci_dev(mdev)->dev,
-                       ms->dma_cmd_size, &dma_cmd_bus, GFP_KERNEL);
+       dma_cmd_space = dma_alloc_coherent(&macio_get_pci_dev(mdev)->dev,
+                                          ms->dma_cmd_size, &dma_cmd_bus,
+                                          GFP_KERNEL);
        if (dma_cmd_space == NULL) {
                printk(KERN_ERR "mesh: can't allocate DMA table\n");
                goto out_unmap;
index dbe753f..36f6420 100644 (file)
@@ -143,8 +143,9 @@ static struct mvumi_res *mvumi_alloc_mem_resource(struct mvumi_hba *mhba,
 
        case RESOURCE_UNCACHED_MEMORY:
                size = round_up(size, 8);
-               res->virt_addr = dma_zalloc_coherent(&mhba->pdev->dev, size,
-                               &res->bus_addr, GFP_KERNEL);
+               res->virt_addr = dma_alloc_coherent(&mhba->pdev->dev, size,
+                                                   &res->bus_addr,
+                                                   GFP_KERNEL);
                if (!res->virt_addr) {
                        dev_err(&mhba->pdev->dev,
                                        "unable to allocate consistent mem,"
@@ -246,8 +247,8 @@ static int mvumi_internal_cmd_sgl(struct mvumi_hba *mhba, struct mvumi_cmd *cmd,
        if (size == 0)
                return 0;
 
-       virt_addr = dma_zalloc_coherent(&mhba->pdev->dev, size, &phy_addr,
-                       GFP_KERNEL);
+       virt_addr = dma_alloc_coherent(&mhba->pdev->dev, size, &phy_addr,
+                                      GFP_KERNEL);
        if (!virt_addr)
                return -1;
 
index b3be49d..084f2fc 100644 (file)
@@ -116,8 +116,8 @@ int pm8001_mem_alloc(struct pci_dev *pdev, void **virt_addr,
        u64 align_offset = 0;
        if (align)
                align_offset = (dma_addr_t)align - 1;
-       mem_virt_alloc = dma_zalloc_coherent(&pdev->dev, mem_size + align,
-                       &mem_dma_handle, GFP_KERNEL);
+       mem_virt_alloc = dma_alloc_coherent(&pdev->dev, mem_size + align,
+                                           &mem_dma_handle, GFP_KERNEL);
        if (!mem_virt_alloc) {
                pm8001_printk("memory allocation error\n");
                return -1;
@@ -657,7 +657,7 @@ static int pm8001_dev_found_notify(struct domain_device *dev)
                if (dev->dev_type == SAS_SATA_DEV) {
                        pm8001_device->attached_phy =
                                dev->rphy->identify.phy_identifier;
-                               flag = 1; /* directly sata*/
+                       flag = 1; /* directly sata */
                }
        } /*register this device to HBA*/
        PM8001_DISC_DBG(pm8001_ha, pm8001_printk("Found device\n"));
index edcaf4b..9bbc19f 100644 (file)
@@ -1050,16 +1050,17 @@ static int qedf_alloc_sq(struct qedf_ctx *qedf, struct qedf_rport *fcport)
            sizeof(void *);
        fcport->sq_pbl_size = fcport->sq_pbl_size + QEDF_PAGE_SIZE;
 
-       fcport->sq = dma_zalloc_coherent(&qedf->pdev->dev,
-           fcport->sq_mem_size, &fcport->sq_dma, GFP_KERNEL);
+       fcport->sq = dma_alloc_coherent(&qedf->pdev->dev, fcport->sq_mem_size,
+                                       &fcport->sq_dma, GFP_KERNEL);
        if (!fcport->sq) {
                QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate send queue.\n");
                rval = 1;
                goto out;
        }
 
-       fcport->sq_pbl = dma_zalloc_coherent(&qedf->pdev->dev,
-           fcport->sq_pbl_size, &fcport->sq_pbl_dma, GFP_KERNEL);
+       fcport->sq_pbl = dma_alloc_coherent(&qedf->pdev->dev,
+                                           fcport->sq_pbl_size,
+                                           &fcport->sq_pbl_dma, GFP_KERNEL);
        if (!fcport->sq_pbl) {
                QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate send queue PBL.\n");
                rval = 1;
@@ -2680,8 +2681,10 @@ static int qedf_alloc_bdq(struct qedf_ctx *qedf)
        }
 
        /* Allocate list of PBL pages */
-       qedf->bdq_pbl_list = dma_zalloc_coherent(&qedf->pdev->dev,
-           QEDF_PAGE_SIZE, &qedf->bdq_pbl_list_dma, GFP_KERNEL);
+       qedf->bdq_pbl_list = dma_alloc_coherent(&qedf->pdev->dev,
+                                               QEDF_PAGE_SIZE,
+                                               &qedf->bdq_pbl_list_dma,
+                                               GFP_KERNEL);
        if (!qedf->bdq_pbl_list) {
                QEDF_ERR(&(qedf->dbg_ctx), "Could not allocate list of PBL pages.\n");
                return -ENOMEM;
@@ -2770,9 +2773,10 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf)
                    ALIGN(qedf->global_queues[i]->cq_pbl_size, QEDF_PAGE_SIZE);
 
                qedf->global_queues[i]->cq =
-                   dma_zalloc_coherent(&qedf->pdev->dev,
-                       qedf->global_queues[i]->cq_mem_size,
-                       &qedf->global_queues[i]->cq_dma, GFP_KERNEL);
+                   dma_alloc_coherent(&qedf->pdev->dev,
+                                      qedf->global_queues[i]->cq_mem_size,
+                                      &qedf->global_queues[i]->cq_dma,
+                                      GFP_KERNEL);
 
                if (!qedf->global_queues[i]->cq) {
                        QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate cq.\n");
@@ -2781,9 +2785,10 @@ static int qedf_alloc_global_queues(struct qedf_ctx *qedf)
                }
 
                qedf->global_queues[i]->cq_pbl =
-                   dma_zalloc_coherent(&qedf->pdev->dev,
-                       qedf->global_queues[i]->cq_pbl_size,
-                       &qedf->global_queues[i]->cq_pbl_dma, GFP_KERNEL);
+                   dma_alloc_coherent(&qedf->pdev->dev,
+                                      qedf->global_queues[i]->cq_pbl_size,
+                                      &qedf->global_queues[i]->cq_pbl_dma,
+                                      GFP_KERNEL);
 
                if (!qedf->global_queues[i]->cq_pbl) {
                        QEDF_WARN(&(qedf->dbg_ctx), "Could not allocate cq PBL.\n");
index 4da660c..6d6d601 100644 (file)
@@ -953,6 +953,7 @@ static int qedi_ep_poll(struct iscsi_endpoint *ep, int timeout_ms)
 
        qedi_ep = ep->dd_data;
        if (qedi_ep->state == EP_STATE_IDLE ||
+           qedi_ep->state == EP_STATE_OFLDCONN_NONE ||
            qedi_ep->state == EP_STATE_OFLDCONN_FAILED)
                return -1;
 
@@ -1035,6 +1036,7 @@ static void qedi_ep_disconnect(struct iscsi_endpoint *ep)
 
        switch (qedi_ep->state) {
        case EP_STATE_OFLDCONN_START:
+       case EP_STATE_OFLDCONN_NONE:
                goto ep_release_conn;
        case EP_STATE_OFLDCONN_FAILED:
                        break;
@@ -1225,6 +1227,7 @@ static int qedi_set_path(struct Scsi_Host *shost, struct iscsi_path *path_data)
 
        if (!is_valid_ether_addr(&path_data->mac_addr[0])) {
                QEDI_NOTICE(&qedi->dbg_ctx, "dst mac NOT VALID\n");
+               qedi_ep->state = EP_STATE_OFLDCONN_NONE;
                ret = -EIO;
                goto set_path_exit;
        }
index 1126077..892d70d 100644 (file)
@@ -59,6 +59,7 @@ enum {
        EP_STATE_OFLDCONN_FAILED        = 0x2000,
        EP_STATE_CONNECT_FAILED         = 0x4000,
        EP_STATE_DISCONN_TIMEDOUT       = 0x8000,
+       EP_STATE_OFLDCONN_NONE          = 0x10000,
 };
 
 struct qedi_conn;
index 5c53409..e74a624 100644 (file)
@@ -1394,10 +1394,9 @@ static int qedi_alloc_nvm_iscsi_cfg(struct qedi_ctx *qedi)
 {
        struct qedi_nvm_iscsi_image nvm_image;
 
-       qedi->iscsi_image = dma_zalloc_coherent(&qedi->pdev->dev,
-                                               sizeof(nvm_image),
-                                               &qedi->nvm_buf_dma,
-                                               GFP_KERNEL);
+       qedi->iscsi_image = dma_alloc_coherent(&qedi->pdev->dev,
+                                              sizeof(nvm_image),
+                                              &qedi->nvm_buf_dma, GFP_KERNEL);
        if (!qedi->iscsi_image) {
                QEDI_ERR(&qedi->dbg_ctx, "Could not allocate NVM BUF.\n");
                return -ENOMEM;
@@ -1510,10 +1509,10 @@ static int qedi_alloc_bdq(struct qedi_ctx *qedi)
        }
 
        /* Allocate list of PBL pages */
-       qedi->bdq_pbl_list = dma_zalloc_coherent(&qedi->pdev->dev,
-                                                QEDI_PAGE_SIZE,
-                                                &qedi->bdq_pbl_list_dma,
-                                                GFP_KERNEL);
+       qedi->bdq_pbl_list = dma_alloc_coherent(&qedi->pdev->dev,
+                                               QEDI_PAGE_SIZE,
+                                               &qedi->bdq_pbl_list_dma,
+                                               GFP_KERNEL);
        if (!qedi->bdq_pbl_list) {
                QEDI_ERR(&qedi->dbg_ctx,
                         "Could not allocate list of PBL pages.\n");
@@ -1609,10 +1608,10 @@ static int qedi_alloc_global_queues(struct qedi_ctx *qedi)
                    (qedi->global_queues[i]->cq_pbl_size +
                    (QEDI_PAGE_SIZE - 1));
 
-               qedi->global_queues[i]->cq = dma_zalloc_coherent(&qedi->pdev->dev,
-                                                                qedi->global_queues[i]->cq_mem_size,
-                                                                &qedi->global_queues[i]->cq_dma,
-                                                                GFP_KERNEL);
+               qedi->global_queues[i]->cq = dma_alloc_coherent(&qedi->pdev->dev,
+                                                               qedi->global_queues[i]->cq_mem_size,
+                                                               &qedi->global_queues[i]->cq_dma,
+                                                               GFP_KERNEL);
 
                if (!qedi->global_queues[i]->cq) {
                        QEDI_WARN(&qedi->dbg_ctx,
@@ -1620,10 +1619,10 @@ static int qedi_alloc_global_queues(struct qedi_ctx *qedi)
                        status = -ENOMEM;
                        goto mem_alloc_failure;
                }
-               qedi->global_queues[i]->cq_pbl = dma_zalloc_coherent(&qedi->pdev->dev,
-                                                                    qedi->global_queues[i]->cq_pbl_size,
-                                                                    &qedi->global_queues[i]->cq_pbl_dma,
-                                                                    GFP_KERNEL);
+               qedi->global_queues[i]->cq_pbl = dma_alloc_coherent(&qedi->pdev->dev,
+                                                                   qedi->global_queues[i]->cq_pbl_size,
+                                                                   &qedi->global_queues[i]->cq_pbl_dma,
+                                                                   GFP_KERNEL);
 
                if (!qedi->global_queues[i]->cq_pbl) {
                        QEDI_WARN(&qedi->dbg_ctx,
@@ -1691,16 +1690,16 @@ int qedi_alloc_sq(struct qedi_ctx *qedi, struct qedi_endpoint *ep)
        ep->sq_pbl_size = (ep->sq_mem_size / QEDI_PAGE_SIZE) * sizeof(void *);
        ep->sq_pbl_size = ep->sq_pbl_size + QEDI_PAGE_SIZE;
 
-       ep->sq = dma_zalloc_coherent(&qedi->pdev->dev, ep->sq_mem_size,
-                                    &ep->sq_dma, GFP_KERNEL);
+       ep->sq = dma_alloc_coherent(&qedi->pdev->dev, ep->sq_mem_size,
+                                   &ep->sq_dma, GFP_KERNEL);
        if (!ep->sq) {
                QEDI_WARN(&qedi->dbg_ctx,
                          "Could not allocate send queue.\n");
                rval = -ENOMEM;
                goto out;
        }
-       ep->sq_pbl = dma_zalloc_coherent(&qedi->pdev->dev, ep->sq_pbl_size,
-                                        &ep->sq_pbl_dma, GFP_KERNEL);
+       ep->sq_pbl = dma_alloc_coherent(&qedi->pdev->dev, ep->sq_pbl_size,
+                                       &ep->sq_pbl_dma, GFP_KERNEL);
        if (!ep->sq_pbl) {
                QEDI_WARN(&qedi->dbg_ctx,
                          "Could not allocate send queue PBL.\n");
index a414f51..6856dfd 100644 (file)
@@ -4248,7 +4248,7 @@ qla1280_probe_one(struct pci_dev *pdev, const struct pci_device_id *id)
        ha->devnum = devnum;    /* specifies microcode load address */
 
 #ifdef QLA_64BIT_PTR
-       if (dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(64))) {
+       if (dma_set_mask_and_coherent(&ha->pdev->dev, DMA_BIT_MASK(64))) {
                if (dma_set_mask(&ha->pdev->dev, DMA_BIT_MASK(32))) {
                        printk(KERN_WARNING "scsi(%li): Unable to set a "
                               "suitable DMA mask - aborting\n", ha->host_no);
index 00444dc..ac504a1 100644 (file)
@@ -2415,8 +2415,8 @@ qla2x00_get_fc_host_stats(struct Scsi_Host *shost)
        if (qla2x00_chip_is_down(vha))
                goto done;
 
-       stats = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*stats),
-                                   &stats_dma, GFP_KERNEL);
+       stats = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stats), &stats_dma,
+                                  GFP_KERNEL);
        if (!stats) {
                ql_log(ql_log_warn, vha, 0x707d,
                    "Failed to allocate memory for stats.\n");
index 4a9fd8d..17d4265 100644 (file)
@@ -2312,8 +2312,8 @@ qla2x00_get_priv_stats(struct bsg_job *bsg_job)
        if (!IS_FWI2_CAPABLE(ha))
                return -EPERM;
 
-       stats = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*stats),
-                                   &stats_dma, GFP_KERNEL);
+       stats = dma_alloc_coherent(&ha->pdev->dev, sizeof(*stats), &stats_dma,
+                                  GFP_KERNEL);
        if (!stats) {
                ql_log(ql_log_warn, vha, 0x70e2,
                    "Failed to allocate memory for stats.\n");
index 26b93c5..d1fc495 100644 (file)
@@ -4394,6 +4394,8 @@ typedef struct scsi_qla_host {
        uint16_t        n2n_id;
        struct list_head gpnid_list;
        struct fab_scan scan;
+
+       unsigned int irq_offset;
 } scsi_qla_host_t;
 
 struct qla27xx_image_status {
index 90cfa39..cbc3bc4 100644 (file)
@@ -4147,9 +4147,10 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
                        return rval;
                }
 
-               sp->u.iocb_cmd.u.ctarg.req = dma_zalloc_coherent(
-                       &vha->hw->pdev->dev, sizeof(struct ct_sns_pkt),
-                       &sp->u.iocb_cmd.u.ctarg.req_dma, GFP_KERNEL);
+               sp->u.iocb_cmd.u.ctarg.req = dma_alloc_coherent(&vha->hw->pdev->dev,
+                                                               sizeof(struct ct_sns_pkt),
+                                                               &sp->u.iocb_cmd.u.ctarg.req_dma,
+                                                               GFP_KERNEL);
                sp->u.iocb_cmd.u.ctarg.req_allocated_size = sizeof(struct ct_sns_pkt);
                if (!sp->u.iocb_cmd.u.ctarg.req) {
                        ql_log(ql_log_warn, vha, 0xffff,
@@ -4165,9 +4166,10 @@ int qla24xx_async_gpnft(scsi_qla_host_t *vha, u8 fc4_type, srb_t *sp)
                        ((vha->hw->max_fibre_devices - 1) *
                            sizeof(struct ct_sns_gpn_ft_data));
 
-               sp->u.iocb_cmd.u.ctarg.rsp = dma_zalloc_coherent(
-                       &vha->hw->pdev->dev, rspsz,
-                       &sp->u.iocb_cmd.u.ctarg.rsp_dma, GFP_KERNEL);
+               sp->u.iocb_cmd.u.ctarg.rsp = dma_alloc_coherent(&vha->hw->pdev->dev,
+                                                               rspsz,
+                                                               &sp->u.iocb_cmd.u.ctarg.rsp_dma,
+                                                               GFP_KERNEL);
                sp->u.iocb_cmd.u.ctarg.rsp_allocated_size = sizeof(struct ct_sns_pkt);
                if (!sp->u.iocb_cmd.u.ctarg.rsp) {
                        ql_log(ql_log_warn, vha, 0xffff,
index 364bb52..8d1acc8 100644 (file)
@@ -1785,13 +1785,13 @@ qla2x00_async_tm_cmd(fc_port_t *fcport, uint32_t flags, uint32_t lun,
 
                /* Issue Marker IOCB */
                qla2x00_marker(vha, vha->hw->req_q_map[0],
-                   vha->hw->rsp_q_map[0], sp->fcport->loop_id, lun,
+                   vha->hw->rsp_q_map[0], fcport->loop_id, lun,
                    flags == TCF_LUN_RESET ? MK_SYNC_ID_LUN : MK_SYNC_ID);
        }
 
 done_free_sp:
        sp->free(sp);
-       sp->fcport->flags &= ~FCF_ASYNC_SENT;
+       fcport->flags &= ~FCF_ASYNC_SENT;
 done:
        return rval;
 }
@@ -3099,8 +3099,8 @@ qla2x00_alloc_offload_mem(scsi_qla_host_t *vha)
                            FCE_SIZE, ha->fce, ha->fce_dma);
 
                /* Allocate memory for Fibre Channel Event Buffer. */
-               tc = dma_zalloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
-                                        GFP_KERNEL);
+               tc = dma_alloc_coherent(&ha->pdev->dev, FCE_SIZE, &tc_dma,
+                                       GFP_KERNEL);
                if (!tc) {
                        ql_log(ql_log_warn, vha, 0x00be,
                            "Unable to allocate (%d KB) for FCE.\n",
@@ -3131,8 +3131,8 @@ try_eft:
                            EFT_SIZE, ha->eft, ha->eft_dma);
 
                /* Allocate memory for Extended Trace Buffer. */
-               tc = dma_zalloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
-                                        GFP_KERNEL);
+               tc = dma_alloc_coherent(&ha->pdev->dev, EFT_SIZE, &tc_dma,
+                                       GFP_KERNEL);
                if (!tc) {
                        ql_log(ql_log_warn, vha, 0x00c1,
                            "Unable to allocate (%d KB) for EFT.\n",
index 30d3090..8507c43 100644 (file)
@@ -3446,6 +3446,7 @@ qla24xx_enable_msix(struct qla_hw_data *ha, struct rsp_que *rsp)
                            "Adjusted Max no of queues pairs: %d.\n", ha->max_qpairs);
                }
        }
+       vha->irq_offset = desc.pre_vectors;
        ha->msix_entries = kcalloc(ha->msix_count,
                                   sizeof(struct qla_msix_entry),
                                   GFP_KERNEL);
index ea69daf..c6ef83d 100644 (file)
@@ -6939,7 +6939,7 @@ static int qla2xxx_map_queues(struct Scsi_Host *shost)
        if (USER_CTRL_IRQ(vha->hw))
                rc = blk_mq_map_queues(qmap);
        else
-               rc = blk_mq_pci_map_queues(qmap, vha->hw->pdev, 0);
+               rc = blk_mq_pci_map_queues(qmap, vha->hw->pdev, vha->irq_offset);
        return rc;
 }
 
index 1ef74aa..2bf5e3e 100644 (file)
@@ -153,8 +153,8 @@ int qla4xxx_get_sys_info(struct scsi_qla_host *ha)
        dma_addr_t sys_info_dma;
        int status = QLA_ERROR;
 
-       sys_info = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*sys_info),
-                                      &sys_info_dma, GFP_KERNEL);
+       sys_info = dma_alloc_coherent(&ha->pdev->dev, sizeof(*sys_info),
+                                     &sys_info_dma, GFP_KERNEL);
        if (sys_info == NULL) {
                DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
                              ha->host_no, __func__));
index 5d56904..dac9a70 100644 (file)
@@ -625,9 +625,9 @@ int qla4xxx_initialize_fw_cb(struct scsi_qla_host * ha)
        uint32_t mbox_sts[MBOX_REG_COUNT];
        int status = QLA_ERROR;
 
-       init_fw_cb = dma_zalloc_coherent(&ha->pdev->dev,
-                                        sizeof(struct addr_ctrl_blk),
-                                        &init_fw_cb_dma, GFP_KERNEL);
+       init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
+                                       sizeof(struct addr_ctrl_blk),
+                                       &init_fw_cb_dma, GFP_KERNEL);
        if (init_fw_cb == NULL) {
                DEBUG2(printk("scsi%ld: %s: Unable to alloc init_cb\n",
                              ha->host_no, __func__));
@@ -709,9 +709,9 @@ int qla4xxx_get_dhcp_ip_address(struct scsi_qla_host * ha)
        uint32_t mbox_cmd[MBOX_REG_COUNT];
        uint32_t mbox_sts[MBOX_REG_COUNT];
 
-       init_fw_cb = dma_zalloc_coherent(&ha->pdev->dev,
-                                        sizeof(struct addr_ctrl_blk),
-                                        &init_fw_cb_dma, GFP_KERNEL);
+       init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
+                                       sizeof(struct addr_ctrl_blk),
+                                       &init_fw_cb_dma, GFP_KERNEL);
        if (init_fw_cb == NULL) {
                printk("scsi%ld: %s: Unable to alloc init_cb\n", ha->host_no,
                       __func__);
@@ -1340,9 +1340,9 @@ int qla4xxx_about_firmware(struct scsi_qla_host *ha)
        uint32_t mbox_sts[MBOX_REG_COUNT];
        int status = QLA_ERROR;
 
-       about_fw = dma_zalloc_coherent(&ha->pdev->dev,
-                                      sizeof(struct about_fw_info),
-                                      &about_fw_dma, GFP_KERNEL);
+       about_fw = dma_alloc_coherent(&ha->pdev->dev,
+                                     sizeof(struct about_fw_info),
+                                     &about_fw_dma, GFP_KERNEL);
        if (!about_fw) {
                DEBUG2(ql4_printk(KERN_ERR, ha, "%s: Unable to alloc memory "
                                  "for about_fw\n", __func__));
index d2b333d..5a31877 100644 (file)
@@ -4052,8 +4052,8 @@ int qla4_8xxx_get_sys_info(struct scsi_qla_host *ha)
        dma_addr_t sys_info_dma;
        int status = QLA_ERROR;
 
-       sys_info = dma_zalloc_coherent(&ha->pdev->dev, sizeof(*sys_info),
-                                      &sys_info_dma, GFP_KERNEL);
+       sys_info = dma_alloc_coherent(&ha->pdev->dev, sizeof(*sys_info),
+                                     &sys_info_dma, GFP_KERNEL);
        if (sys_info == NULL) {
                DEBUG2(printk("scsi%ld: %s: Unable to allocate dma buffer.\n",
                    ha->host_no, __func__));
index 949e186..a77bfb2 100644 (file)
@@ -2704,9 +2704,9 @@ qla4xxx_iface_set_param(struct Scsi_Host *shost, void *data, uint32_t len)
        uint32_t rem = len;
        struct nlattr *attr;
 
-       init_fw_cb = dma_zalloc_coherent(&ha->pdev->dev,
-                                        sizeof(struct addr_ctrl_blk),
-                                        &init_fw_cb_dma, GFP_KERNEL);
+       init_fw_cb = dma_alloc_coherent(&ha->pdev->dev,
+                                       sizeof(struct addr_ctrl_blk),
+                                       &init_fw_cb_dma, GFP_KERNEL);
        if (!init_fw_cb) {
                ql4_printk(KERN_ERR, ha, "%s: Unable to alloc init_cb\n",
                           __func__);
@@ -4206,8 +4206,8 @@ static int qla4xxx_mem_alloc(struct scsi_qla_host *ha)
                          sizeof(struct shadow_regs) +
                          MEM_ALIGN_VALUE +
                          (PAGE_SIZE - 1)) & ~(PAGE_SIZE - 1);
-       ha->queues = dma_zalloc_coherent(&ha->pdev->dev, ha->queues_len,
-                                        &ha->queues_dma, GFP_KERNEL);
+       ha->queues = dma_alloc_coherent(&ha->pdev->dev, ha->queues_len,
+                                       &ha->queues_dma, GFP_KERNEL);
        if (ha->queues == NULL) {
                ql4_printk(KERN_WARNING, ha,
                    "Memory Allocation failed - queues.\n");
@@ -7232,6 +7232,8 @@ static int qla4xxx_sysfs_ddb_tgt_create(struct scsi_qla_host *ha,
 
        rc = qla4xxx_copy_from_fwddb_param(fnode_sess, fnode_conn,
                                           fw_ddb_entry);
+       if (rc)
+               goto free_sess;
 
        ql4_printk(KERN_INFO, ha, "%s: sysfs entry %s created\n",
                   __func__, fnode_sess->dev.kobj.name);
index 661512b..e27f4df 100644 (file)
@@ -62,7 +62,7 @@
 
 /* make sure inq_product_rev string corresponds to this version */
 #define SDEBUG_VERSION "0188"  /* format to fit INQUIRY revision field */
-static const char *sdebug_version_date = "20180128";
+static const char *sdebug_version_date = "20190125";
 
 #define MY_NAME "scsi_debug"
 
@@ -735,7 +735,7 @@ static inline bool scsi_debug_lbp(void)
                (sdebug_lbpu || sdebug_lbpws || sdebug_lbpws10);
 }
 
-static void *fake_store(unsigned long long lba)
+static void *lba2fake_store(unsigned long long lba)
 {
        lba = do_div(lba, sdebug_store_sectors);
 
@@ -2514,8 +2514,8 @@ static int do_device_access(struct scsi_cmnd *scmd, u32 sg_skip, u64 lba,
        return ret;
 }
 
-/* If fake_store(lba,num) compares equal to arr(num), then copy top half of
- * arr into fake_store(lba,num) and return true. If comparison fails then
+/* If lba2fake_store(lba,num) compares equal to arr(num), then copy top half of
+ * arr into lba2fake_store(lba,num) and return true. If comparison fails then
  * return false. */
 static bool comp_write_worker(u64 lba, u32 num, const u8 *arr)
 {
@@ -2643,7 +2643,7 @@ static int prot_verify_read(struct scsi_cmnd *SCpnt, sector_t start_sec,
                if (sdt->app_tag == cpu_to_be16(0xffff))
                        continue;
 
-               ret = dif_verify(sdt, fake_store(sector), sector, ei_lba);
+               ret = dif_verify(sdt, lba2fake_store(sector), sector, ei_lba);
                if (ret) {
                        dif_errors++;
                        return ret;
@@ -3261,10 +3261,12 @@ err_out:
 static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
                           u32 ei_lba, bool unmap, bool ndob)
 {
+       int ret;
        unsigned long iflags;
        unsigned long long i;
-       int ret;
-       u64 lba_off;
+       u32 lb_size = sdebug_sector_size;
+       u64 block, lbaa;
+       u8 *fs1p;
 
        ret = check_device_access_params(scp, lba, num);
        if (ret)
@@ -3276,31 +3278,30 @@ static int resp_write_same(struct scsi_cmnd *scp, u64 lba, u32 num,
                unmap_region(lba, num);
                goto out;
        }
-
-       lba_off = lba * sdebug_sector_size;
+       lbaa = lba;
+       block = do_div(lbaa, sdebug_store_sectors);
        /* if ndob then zero 1 logical block, else fetch 1 logical block */
+       fs1p = fake_storep + (block * lb_size);
        if (ndob) {
-               memset(fake_storep + lba_off, 0, sdebug_sector_size);
+               memset(fs1p, 0, lb_size);
                ret = 0;
        } else
-               ret = fetch_to_dev_buffer(scp, fake_storep + lba_off,
-                                         sdebug_sector_size);
+               ret = fetch_to_dev_buffer(scp, fs1p, lb_size);
 
        if (-1 == ret) {
                write_unlock_irqrestore(&atomic_rw, iflags);
                return DID_ERROR << 16;
-       } else if (sdebug_verbose && !ndob && (ret < sdebug_sector_size))
+       } else if (sdebug_verbose && !ndob && (ret < lb_size))
                sdev_printk(KERN_INFO, scp->device,
                            "%s: %s: lb size=%u, IO sent=%d bytes\n",
-                           my_name, "write same",
-                           sdebug_sector_size, ret);
+                           my_name, "write same", lb_size, ret);
 
        /* Copy first sector to remaining blocks */
-       for (i = 1 ; i < num ; i++)
-               memcpy(fake_storep + ((lba + i) * sdebug_sector_size),
-                      fake_storep + lba_off,
-                      sdebug_sector_size);
-
+       for (i = 1 ; i < num ; i++) {
+               lbaa = lba + i;
+               block = do_div(lbaa, sdebug_store_sectors);
+               memmove(fake_storep + (block * lb_size), fs1p, lb_size);
+       }
        if (scsi_debug_lbp())
                map_region(lba, num);
 out:
index b13cc92..f8d51c3 100644 (file)
@@ -655,6 +655,7 @@ static blk_status_t scsi_result_to_blk_status(struct scsi_cmnd *cmd, int result)
                set_host_byte(cmd, DID_OK);
                return BLK_STS_TARGET;
        case DID_NEXUS_FAILURE:
+               set_host_byte(cmd, DID_OK);
                return BLK_STS_NEXUS;
        case DID_ALLOC_FAILURE:
                set_host_byte(cmd, DID_OK);
@@ -1842,8 +1843,8 @@ void __scsi_init_queue(struct Scsi_Host *shost, struct request_queue *q)
        blk_queue_segment_boundary(q, shost->dma_boundary);
        dma_set_seg_boundary(dev, shost->dma_boundary);
 
-       blk_queue_max_segment_size(q,
-               min(shost->max_segment_size, dma_get_max_seg_size(dev)));
+       blk_queue_max_segment_size(q, shost->max_segment_size);
+       dma_set_max_seg_size(dev, shost->max_segment_size);
 
        /*
         * Set a reasonable default alignment:  The larger of 32-byte (dword),
index a2b4179..7639df9 100644 (file)
@@ -80,8 +80,22 @@ static int scsi_dev_type_resume(struct device *dev,
 
        if (err == 0) {
                pm_runtime_disable(dev);
-               pm_runtime_set_active(dev);
+               err = pm_runtime_set_active(dev);
                pm_runtime_enable(dev);
+
+               /*
+                * Forcibly set runtime PM status of request queue to "active"
+                * to make sure we can again get requests from the queue
+                * (see also blk_pm_peek_request()).
+                *
+                * The resume hook will correct runtime PM status of the disk.
+                */
+               if (!err && scsi_is_sdev_device(dev)) {
+                       struct scsi_device *sdev = to_scsi_device(dev);
+
+                       if (sdev->request_queue->dev)
+                               blk_set_runtime_active(sdev->request_queue);
+               }
        }
 
        return err;
@@ -140,16 +154,6 @@ static int scsi_bus_resume_common(struct device *dev,
        else
                fn = NULL;
 
-       /*
-        * Forcibly set runtime PM status of request queue to "active" to
-        * make sure we can again get requests from the queue (see also
-        * blk_pm_peek_request()).
-        *
-        * The resume hook will correct runtime PM status of the disk.
-        */
-       if (scsi_is_sdev_device(dev) && pm_runtime_suspended(dev))
-               blk_set_runtime_active(to_scsi_device(dev)->request_queue);
-
        if (fn) {
                async_schedule_domain(fn, dev, &scsi_sd_pm_domain);
 
index a1a44f5..5464d46 100644 (file)
@@ -206,6 +206,12 @@ cache_type_store(struct device *dev, struct device_attribute *attr,
        sp = buffer_data[0] & 0x80 ? 1 : 0;
        buffer_data[0] &= ~0x80;
 
+       /*
+        * Ensure WP, DPOFUA, and RESERVED fields are cleared in
+        * received mode parameter buffer before doing MODE SELECT.
+        */
+       data.device_specific = 0;
+
        if (scsi_mode_select(sdp, 1, sp, 8, buffer_data, len, SD_TIMEOUT,
                             SD_MAX_RETRIES, &data, &sshdr)) {
                if (scsi_sense_valid(&sshdr))
@@ -2945,9 +2951,6 @@ static void sd_read_block_characteristics(struct scsi_disk *sdkp)
        if (rot == 1) {
                blk_queue_flag_set(QUEUE_FLAG_NONROT, q);
                blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, q);
-       } else {
-               blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
-               blk_queue_flag_set(QUEUE_FLAG_ADD_RANDOM, q);
        }
 
        if (sdkp->device->type == TYPE_ZBC) {
@@ -3084,6 +3087,15 @@ static int sd_revalidate_disk(struct gendisk *disk)
        if (sdkp->media_present) {
                sd_read_capacity(sdkp, buffer);
 
+               /*
+                * set the default to rotational.  All non-rotational devices
+                * support the block characteristics VPD page, which will
+                * cause this to be updated correctly and any device which
+                * doesn't support it should be treated as rotational.
+                */
+               blk_queue_flag_clear(QUEUE_FLAG_NONROT, q);
+               blk_queue_flag_set(QUEUE_FLAG_ADD_RANDOM, q);
+
                if (scsi_device_supports_vpd(sdp)) {
                        sd_read_block_provisioning(sdkp);
                        sd_read_block_limits(sdkp);
index 83365b2..a340af7 100644 (file)
@@ -142,10 +142,12 @@ int sd_zbc_report_zones(struct gendisk *disk, sector_t sector,
                return -EOPNOTSUPP;
 
        /*
-        * Get a reply buffer for the number of requested zones plus a header.
-        * For ATA, buffers must be aligned to 512B.
+        * Get a reply buffer for the number of requested zones plus a header,
+        * without exceeding the device maximum command size. For ATA disks,
+        * buffers must be aligned to 512B.
         */
-       buflen = roundup((nrz + 1) * 64, 512);
+       buflen = min(queue_max_hw_sectors(disk->queue) << 9,
+                    roundup((nrz + 1) * 64, 512));
        buf = kmalloc(buflen, gfp_mask);
        if (!buf)
                return -ENOMEM;
@@ -462,12 +464,16 @@ int sd_zbc_read_zones(struct scsi_disk *sdkp, unsigned char *buf)
        sdkp->device->use_10_for_rw = 0;
 
        /*
-        * If something changed, revalidate the disk zone bitmaps once we have
-        * the capacity, that is on the second revalidate execution during disk
-        * scan and always during normal revalidate.
+        * Revalidate the disk zone bitmaps once the block device capacity is
+        * set on the second revalidate execution during disk scan and if
+        * something changed when executing a normal revalidate.
         */
-       if (sdkp->first_scan)
+       if (sdkp->first_scan) {
+               sdkp->zone_blocks = zone_blocks;
+               sdkp->nr_zones = nr_zones;
                return 0;
+       }
+
        if (sdkp->zone_blocks != zone_blocks ||
            sdkp->nr_zones != nr_zones ||
            disk->queue->nr_zones != nr_zones) {
index e2fa3f4..f564af8 100644 (file)
@@ -323,7 +323,7 @@ static inline void pqi_device_remove_start(struct pqi_scsi_dev *device)
 static inline bool pqi_device_in_remove(struct pqi_ctrl_info *ctrl_info,
                                        struct pqi_scsi_dev *device)
 {
-       return device->in_remove & !ctrl_info->in_shutdown;
+       return device->in_remove && !ctrl_info->in_shutdown;
 }
 
 static inline void pqi_schedule_rescan_worker_with_delay(
@@ -3576,9 +3576,9 @@ static int pqi_alloc_operational_queues(struct pqi_ctrl_info *ctrl_info)
        alloc_length += PQI_EXTRA_SGL_MEMORY;
 
        ctrl_info->queue_memory_base =
-               dma_zalloc_coherent(&ctrl_info->pci_dev->dev,
-                       alloc_length,
-                       &ctrl_info->queue_memory_base_dma_handle, GFP_KERNEL);
+               dma_alloc_coherent(&ctrl_info->pci_dev->dev, alloc_length,
+                                  &ctrl_info->queue_memory_base_dma_handle,
+                                  GFP_KERNEL);
 
        if (!ctrl_info->queue_memory_base)
                return -ENOMEM;
@@ -3715,10 +3715,9 @@ static int pqi_alloc_admin_queues(struct pqi_ctrl_info *ctrl_info)
                PQI_QUEUE_ELEMENT_ARRAY_ALIGNMENT;
 
        ctrl_info->admin_queue_memory_base =
-               dma_zalloc_coherent(&ctrl_info->pci_dev->dev,
-                       alloc_length,
-                       &ctrl_info->admin_queue_memory_base_dma_handle,
-                       GFP_KERNEL);
+               dma_alloc_coherent(&ctrl_info->pci_dev->dev, alloc_length,
+                                  &ctrl_info->admin_queue_memory_base_dma_handle,
+                                  GFP_KERNEL);
 
        if (!ctrl_info->admin_queue_memory_base)
                return -ENOMEM;
@@ -4602,9 +4601,10 @@ static void pqi_free_all_io_requests(struct pqi_ctrl_info *ctrl_info)
 
 static inline int pqi_alloc_error_buffer(struct pqi_ctrl_info *ctrl_info)
 {
-       ctrl_info->error_buffer = dma_zalloc_coherent(&ctrl_info->pci_dev->dev,
-               ctrl_info->error_buffer_length,
-               &ctrl_info->error_buffer_dma_handle, GFP_KERNEL);
+       ctrl_info->error_buffer = dma_alloc_coherent(&ctrl_info->pci_dev->dev,
+                                                    ctrl_info->error_buffer_length,
+                                                    &ctrl_info->error_buffer_dma_handle,
+                                                    GFP_KERNEL);
 
        if (!ctrl_info->error_buffer)
                return -ENOMEM;
@@ -7487,8 +7487,8 @@ static int pqi_ofa_alloc_mem(struct pqi_ctrl_info *ctrl_info,
                dma_addr_t dma_handle;
 
                ctrl_info->pqi_ofa_chunk_virt_addr[i] =
-                       dma_zalloc_coherent(dev, chunk_size, &dma_handle,
-                                               GFP_KERNEL);
+                       dma_alloc_coherent(dev, chunk_size, &dma_handle,
+                                          GFP_KERNEL);
 
                if (!ctrl_info->pqi_ofa_chunk_virt_addr[i])
                        break;
@@ -7545,10 +7545,10 @@ static void pqi_ofa_setup_host_buffer(struct pqi_ctrl_info *ctrl_info,
        struct device *dev;
 
        dev = &ctrl_info->pci_dev->dev;
-       pqi_ofa_memory = dma_zalloc_coherent(dev,
-                               PQI_OFA_MEMORY_DESCRIPTOR_LENGTH,
-                               &ctrl_info->pqi_ofa_mem_dma_handle,
-                               GFP_KERNEL);
+       pqi_ofa_memory = dma_alloc_coherent(dev,
+                                           PQI_OFA_MEMORY_DESCRIPTOR_LENGTH,
+                                           &ctrl_info->pqi_ofa_mem_dma_handle,
+                                           GFP_KERNEL);
 
        if (!pqi_ofa_memory)
                return;
index dd65fea..6d17681 100644 (file)
@@ -195,7 +195,7 @@ enum ufs_desc_def_size {
        QUERY_DESC_CONFIGURATION_DEF_SIZE       = 0x90,
        QUERY_DESC_UNIT_DEF_SIZE                = 0x23,
        QUERY_DESC_INTERCONNECT_DEF_SIZE        = 0x06,
-       QUERY_DESC_GEOMETRY_DEF_SIZE            = 0x44,
+       QUERY_DESC_GEOMETRY_DEF_SIZE            = 0x48,
        QUERY_DESC_POWER_DEF_SIZE               = 0x62,
        QUERY_DESC_HEALTH_DEF_SIZE              = 0x25,
 };
index 9ba7671..2ddf244 100644 (file)
 int ufshcd_dump_regs(struct ufs_hba *hba, size_t offset, size_t len,
                     const char *prefix)
 {
-       u8 *regs;
+       u32 *regs;
+       size_t pos;
+
+       if (offset % 4 != 0 || len % 4 != 0) /* keep readl happy */
+               return -EINVAL;
 
        regs = kzalloc(len, GFP_KERNEL);
        if (!regs)
                return -ENOMEM;
 
-       memcpy_fromio(regs, hba->mmio_base + offset, len);
+       for (pos = 0; pos < len; pos += 4)
+               regs[pos / 4] = ufshcd_readl(hba, offset + pos);
+
        ufshcd_hex_dump(prefix, regs, len);
        kfree(regs);
 
@@ -8001,6 +8007,8 @@ out:
        trace_ufshcd_system_resume(dev_name(hba->dev), ret,
                ktime_to_us(ktime_sub(ktime_get(), start)),
                hba->curr_dev_pwr_mode, hba->uic_link_state);
+       if (!ret)
+               hba->is_sys_suspended = false;
        return ret;
 }
 EXPORT_SYMBOL(ufshcd_system_resume);
index 9436aa8..e6d48dc 100644 (file)
@@ -62,7 +62,7 @@ int qbman_init_private_mem(struct device *dev, int idx, dma_addr_t *addr,
                return -ENODEV;
        }
 
-       if (!dma_zalloc_coherent(dev, *size, addr, 0)) {
+       if (!dma_alloc_coherent(dev, *size, addr, 0)) {
                dev_err(dev, "DMA Alloc memory failed\n");
                return -ENODEV;
        }
index 52c153c..636f83f 100644 (file)
@@ -1143,18 +1143,19 @@ static void qm_mr_process_task(struct work_struct *work);
 static irqreturn_t portal_isr(int irq, void *ptr)
 {
        struct qman_portal *p = ptr;
-
-       u32 clear = QM_DQAVAIL_MASK | p->irq_sources;
        u32 is = qm_in(&p->p, QM_REG_ISR) & p->irq_sources;
+       u32 clear = 0;
 
        if (unlikely(!is))
                return IRQ_NONE;
 
        /* DQRR-handling if it's interrupt-driven */
-       if (is & QM_PIRQ_DQRI)
+       if (is & QM_PIRQ_DQRI) {
                __poll_portal_fast(p, QMAN_POLL_LIMIT);
+               clear = QM_DQAVAIL_MASK | QM_PIRQ_DQRI;
+       }
        /* Handling of anything else that's interrupt-driven */
-       clear |= __poll_portal_slow(p, is);
+       clear |= __poll_portal_slow(p, is) & QM_PIRQ_SLOW;
        qm_out(&p->p, QM_REG_ISR, clear);
        return IRQ_HANDLED;
 }
index f78c346..76480df 100644 (file)
@@ -44,10 +44,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm,
        const char *sprop;
        int ret = 0;
        u32 val;
-       struct resource *res;
-       struct device_node *np2;
-       static int siram_init_flag;
-       struct platform_device *pdev;
 
        sprop = of_get_property(np, "fsl,rx-sync-clock", NULL);
        if (sprop) {
@@ -124,57 +120,6 @@ int ucc_of_parse_tdm(struct device_node *np, struct ucc_tdm *utdm,
        utdm->siram_entry_id = val;
 
        set_si_param(utdm, ut_info);
-
-       np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-si");
-       if (!np2)
-               return -EINVAL;
-
-       pdev = of_find_device_by_node(np2);
-       if (!pdev) {
-               pr_err("%pOFn: failed to lookup pdev\n", np2);
-               of_node_put(np2);
-               return -EINVAL;
-       }
-
-       of_node_put(np2);
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       utdm->si_regs = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(utdm->si_regs)) {
-               ret = PTR_ERR(utdm->si_regs);
-               goto err_miss_siram_property;
-       }
-
-       np2 = of_find_compatible_node(NULL, NULL, "fsl,t1040-qe-siram");
-       if (!np2) {
-               ret = -EINVAL;
-               goto err_miss_siram_property;
-       }
-
-       pdev = of_find_device_by_node(np2);
-       if (!pdev) {
-               ret = -EINVAL;
-               pr_err("%pOFn: failed to lookup pdev\n", np2);
-               of_node_put(np2);
-               goto err_miss_siram_property;
-       }
-
-       of_node_put(np2);
-       res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
-       utdm->siram = devm_ioremap_resource(&pdev->dev, res);
-       if (IS_ERR(utdm->siram)) {
-               ret = PTR_ERR(utdm->siram);
-               goto err_miss_siram_property;
-       }
-
-       if (siram_init_flag == 0) {
-               memset_io(utdm->siram, 0,  resource_size(res));
-               siram_init_flag = 1;
-       }
-
-       return ret;
-
-err_miss_siram_property:
-       devm_iounmap(&pdev->dev, utdm->si_regs);
        return ret;
 }
 EXPORT_SYMBOL(ucc_of_parse_tdm);
index 4d8012e..68bfca6 100644 (file)
@@ -44,7 +44,7 @@ config ARCH_RZN1
        bool
        select ARM_AMBA
 
-if ARM
+if ARM && ARCH_RENESAS
 
 #comment "Renesas ARM SoCs System Type"
 
index e1ac4c0..11050e1 100644 (file)
@@ -28,19 +28,6 @@ static struct rcar_sysc_area r8a774c0_areas[] __initdata = {
        { "3dg-b",      0x100, 1, R8A774C0_PD_3DG_B,    R8A774C0_PD_3DG_A },
 };
 
-static void __init rcar_sysc_fix_parent(struct rcar_sysc_area *areas,
-                                       unsigned int num_areas, u8 id,
-                                       int new_parent)
-{
-       unsigned int i;
-
-       for (i = 0; i < num_areas; i++)
-               if (areas[i].isr_bit == id) {
-                       areas[i].parent = new_parent;
-                       return;
-               }
-}
-
 /* Fixups for RZ/G2E ES1.0 revision */
 static const struct soc_device_attribute r8a774c0[] __initconst = {
        { .soc_id = "r8a774c0", .revision = "ES1.0" },
@@ -50,12 +37,10 @@ static const struct soc_device_attribute r8a774c0[] __initconst = {
 static int __init r8a774c0_sysc_init(void)
 {
        if (soc_device_match(r8a774c0)) {
-               rcar_sysc_fix_parent(r8a774c0_areas,
-                                    ARRAY_SIZE(r8a774c0_areas),
-                                    R8A774C0_PD_3DG_A, R8A774C0_PD_3DG_B);
-               rcar_sysc_fix_parent(r8a774c0_areas,
-                                    ARRAY_SIZE(r8a774c0_areas),
-                                    R8A774C0_PD_3DG_B, R8A774C0_PD_ALWAYS_ON);
+               /* Fix incorrect 3DG hierarchy */
+               swap(r8a774c0_areas[6], r8a774c0_areas[7]);
+               r8a774c0_areas[6].parent = R8A774C0_PD_ALWAYS_ON;
+               r8a774c0_areas[7].parent = R8A774C0_PD_3DG_B;
        }
 
        return 0;
index d7e4e18..1ae9af5 100644 (file)
@@ -466,9 +466,9 @@ static int ring_desc_ring_alloc(struct pic32_sqi *sqi)
        int i;
 
        /* allocate coherent DMAable memory for hardware buffer descriptors. */
-       sqi->bd = dma_zalloc_coherent(&sqi->master->dev,
-                                     sizeof(*bd) * PESQI_BD_COUNT,
-                                     &sqi->bd_dma, GFP_KERNEL);
+       sqi->bd = dma_alloc_coherent(&sqi->master->dev,
+                                    sizeof(*bd) * PESQI_BD_COUNT,
+                                    &sqi->bd_dma, GFP_KERNEL);
        if (!sqi->bd) {
                dev_err(&sqi->master->dev, "failed allocating dma buffer\n");
                return -ENOMEM;
index a0802de..6f5afab 100644 (file)
@@ -248,10 +248,10 @@ static void ion_dma_buf_detatch(struct dma_buf *dmabuf,
        struct ion_dma_buf_attachment *a = attachment->priv;
        struct ion_buffer *buffer = dmabuf->priv;
 
-       free_duped_table(a->table);
        mutex_lock(&buffer->lock);
        list_del(&a->list);
        mutex_unlock(&buffer->lock);
+       free_duped_table(a->table);
 
        kfree(a);
 }
index 21a76a8..6027b19 100644 (file)
@@ -1396,8 +1396,7 @@ static int mtk_qdma_tx_alloc_tx(struct mtk_eth *eth)
        if (!ring->tx_buf)
                goto no_tx_mem;
 
-       ring->tx_dma = dma_zalloc_coherent(eth->dev,
-                                         ring->tx_ring_size * sz,
+       ring->tx_dma = dma_alloc_coherent(eth->dev, ring->tx_ring_size * sz,
                                          &ring->tx_phys,
                                          GFP_ATOMIC | __GFP_ZERO);
        if (!ring->tx_dma)
index 2848fa7..d6248ee 100644 (file)
@@ -170,7 +170,7 @@ int cvm_oct_phy_setup_device(struct net_device *dev)
                return -ENODEV;
 
        priv->last_link = 0;
-       phy_start_aneg(phydev);
+       phy_start(phydev);
 
        return 0;
 no_phy:
index 364d6ea..2f90f60 100644 (file)
@@ -154,7 +154,7 @@ void rtw_wep_encrypt(struct adapter *padapter, u8 *pxmitframe)
 
        pframe = ((struct xmit_frame *)pxmitframe)->buf_addr + hw_hdr_offset;
 
-       crypto_ops = try_then_request_module(lib80211_get_crypto_ops("WEP"), "lib80211_crypt_wep");
+       crypto_ops = lib80211_get_crypto_ops("WEP");
 
        if (!crypto_ops)
                return;
@@ -210,7 +210,7 @@ int rtw_wep_decrypt(struct adapter  *padapter, u8 *precvframe)
                void *crypto_private = NULL;
                int status = _SUCCESS;
                const int keyindex = prxattrib->key_index;
-               struct lib80211_crypto_ops *crypto_ops = try_then_request_module(lib80211_get_crypto_ops("WEP"), "lib80211_crypt_wep");
+               struct lib80211_crypto_ops *crypto_ops = lib80211_get_crypto_ops("WEP");
                char iv[4], icv[4];
 
                if (!crypto_ops) {
@@ -1291,7 +1291,7 @@ u32 rtw_aes_decrypt(struct adapter *padapter, u8 *precvframe)
                        struct sk_buff *skb = ((struct recv_frame *)precvframe)->pkt;
                        void *crypto_private = NULL;
                        u8 *key, *pframe = skb->data;
-                       struct lib80211_crypto_ops *crypto_ops = try_then_request_module(lib80211_get_crypto_ops("CCMP"), "lib80211_crypt_ccmp");
+                       struct lib80211_crypto_ops *crypto_ops = lib80211_get_crypto_ops("CCMP");
                        struct security_priv *psecuritypriv = &padapter->securitypriv;
                        char iv[8], icv[8];
 
index 28cbd6b..dfee698 100644 (file)
@@ -35,6 +35,7 @@ static const struct usb_device_id rtw_usb_id_tbl[] = {
        {USB_DEVICE(0x2001, 0x330F)}, /* DLink DWA-125 REV D1 */
        {USB_DEVICE(0x2001, 0x3310)}, /* Dlink DWA-123 REV D1 */
        {USB_DEVICE(0x2001, 0x3311)}, /* DLink GO-USB-N150 REV B1 */
+       {USB_DEVICE(0x2001, 0x331B)}, /* D-Link DWA-121 rev B1 */
        {USB_DEVICE(0x2357, 0x010c)}, /* TP-Link TL-WN722N v2 */
        {USB_DEVICE(0x0df6, 0x0076)}, /* Sitecom N150 v2 */
        {USB_DEVICE(USB_VENDER_ID_REALTEK, 0xffef)}, /* Rosewill RNX-N150NUB */
index bcc8dfa..9efb4dc 100644 (file)
@@ -850,18 +850,18 @@ enum ieee80211_state {
 #define IP_FMT "%pI4"
 #define IP_ARG(x) (x)
 
-extern __inline int is_multicast_mac_addr(const u8 *addr)
+static inline int is_multicast_mac_addr(const u8 *addr)
 {
         return ((addr[0] != 0xff) && (0x01 & addr[0]));
 }
 
-extern __inline int is_broadcast_mac_addr(const u8 *addr)
+static inline int is_broadcast_mac_addr(const u8 *addr)
 {
        return ((addr[0] == 0xff) && (addr[1] == 0xff) && (addr[2] == 0xff) &&   \
                (addr[3] == 0xff) && (addr[4] == 0xff) && (addr[5] == 0xff));
 }
 
-extern __inline int is_zero_mac_addr(const u8 *addr)
+static inline int is_zero_mac_addr(const u8 *addr)
 {
        return ((addr[0] == 0x00) && (addr[1] == 0x00) && (addr[2] == 0x00) &&   \
                (addr[3] == 0x00) && (addr[4] == 0x00) && (addr[5] == 0x00));
index 7c03b69..6d02904 100644 (file)
@@ -22,7 +22,7 @@ static const struct sdio_device_id sdio_ids[] =
        { SDIO_DEVICE(0x024c, 0xb723), },
        { /* end: all zeroes */                         },
 };
-static const struct acpi_device_id acpi_ids[] __used = {
+static const struct acpi_device_id acpi_ids[] = {
        {"OBDA8723", 0x0000},
        {}
 };
index c92bbd0..005de00 100644 (file)
@@ -265,7 +265,8 @@ static void spk_ttyio_send_xchar(char ch)
                return;
        }
 
-       speakup_tty->ops->send_xchar(speakup_tty, ch);
+       if (speakup_tty->ops->send_xchar)
+               speakup_tty->ops->send_xchar(speakup_tty, ch);
        mutex_unlock(&speakup_tty_mutex);
 }
 
@@ -277,7 +278,8 @@ static void spk_ttyio_tiocmset(unsigned int set, unsigned int clear)
                return;
        }
 
-       speakup_tty->ops->tiocmset(speakup_tty, set, clear);
+       if (speakup_tty->ops->tiocmset)
+               speakup_tty->ops->tiocmset(speakup_tty, set, clear);
        mutex_unlock(&speakup_tty_mutex);
 }
 
index 338b6e9..dd48988 100644 (file)
@@ -407,10 +407,8 @@ create_pagelist(char __user *buf, size_t count, unsigned short type)
        /* Allocate enough storage to hold the page pointers and the page
         * list
         */
-       pagelist = dma_zalloc_coherent(g_dev,
-                                      pagelist_size,
-                                      &dma_addr,
-                                      GFP_KERNEL);
+       pagelist = dma_alloc_coherent(g_dev, pagelist_size, &dma_addr,
+                                     GFP_KERNEL);
 
        vchiq_log_trace(vchiq_arm_log_level, "%s - %pK", __func__, pagelist);
 
index 9e17ec6..53f5a1c 100644 (file)
@@ -446,6 +446,7 @@ remote_event_wait(wait_queue_head_t *wq, struct remote_event *event)
 static inline void
 remote_event_signal_local(wait_queue_head_t *wq, struct remote_event *event)
 {
+       event->fired = 1;
        event->armed = 0;
        wake_up_all(wq);
 }
index 1ab0e85..c9097e7 100644 (file)
@@ -440,12 +440,9 @@ static bool device_init_rings(struct vnt_private *priv)
        void *vir_pool;
 
        /*allocate all RD/TD rings a single pool*/
-       vir_pool = dma_zalloc_coherent(&priv->pcid->dev,
-                                      priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) +
-                                      priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) +
-                                      priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) +
-                                      priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc),
-                                      &priv->pool_dma, GFP_ATOMIC);
+       vir_pool = dma_alloc_coherent(&priv->pcid->dev,
+                                     priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc) + priv->opts.rx_descs1 * sizeof(struct vnt_rx_desc) + priv->opts.tx_descs[0] * sizeof(struct vnt_tx_desc) + priv->opts.tx_descs[1] * sizeof(struct vnt_tx_desc),
+                                     &priv->pool_dma, GFP_ATOMIC);
        if (!vir_pool) {
                dev_err(&priv->pcid->dev, "allocate desc dma memory failed\n");
                return false;
@@ -459,13 +456,9 @@ static bool device_init_rings(struct vnt_private *priv)
        priv->rd1_pool_dma = priv->rd0_pool_dma +
                priv->opts.rx_descs0 * sizeof(struct vnt_rx_desc);
 
-       priv->tx0_bufs = dma_zalloc_coherent(&priv->pcid->dev,
-                                            priv->opts.tx_descs[0] * PKT_BUF_SZ +
-                                            priv->opts.tx_descs[1] * PKT_BUF_SZ +
-                                            CB_BEACON_BUF_SIZE +
-                                            CB_MAX_BUF_SIZE,
-                                            &priv->tx_bufs_dma0,
-                                            GFP_ATOMIC);
+       priv->tx0_bufs = dma_alloc_coherent(&priv->pcid->dev,
+                                           priv->opts.tx_descs[0] * PKT_BUF_SZ + priv->opts.tx_descs[1] * PKT_BUF_SZ + CB_BEACON_BUF_SIZE + CB_MAX_BUF_SIZE,
+                                           &priv->tx_bufs_dma0, GFP_ATOMIC);
        if (!priv->tx0_bufs) {
                dev_err(&priv->pcid->dev, "allocate buf dma memory failed\n");
 
index 70c854d..3d0badc 100644 (file)
@@ -36,7 +36,7 @@ struct wilc_op_mode {
 struct wilc_reg_frame {
        bool reg;
        u8 reg_id;
-       __le32 frame_type;
+       __le16 frame_type;
 } __packed;
 
 struct wilc_drv_handler {
@@ -1744,7 +1744,6 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
                result = wilc_send_config_pkt(vif, WILC_SET_CFG, wid_list,
                                              ARRAY_SIZE(wid_list),
                                              wilc_get_vif_idx(vif));
-               kfree(gtk_key);
        } else if (mode == WILC_STATION_MODE) {
                struct wid wid;
 
@@ -1754,9 +1753,9 @@ int wilc_add_rx_gtk(struct wilc_vif *vif, const u8 *rx_gtk, u8 gtk_key_len,
                wid.val = (u8 *)gtk_key;
                result = wilc_send_config_pkt(vif, WILC_SET_CFG, &wid, 1,
                                              wilc_get_vif_idx(vif));
-               kfree(gtk_key);
        }
 
+       kfree(gtk_key);
        return result;
 }
 
index 3c5e9e0..489e5a5 100644 (file)
@@ -1252,21 +1252,22 @@ static u32 init_chip(struct net_device *dev)
                ret = wilc->hif_func->hif_read_reg(wilc, 0x1118, &reg);
                if (!ret) {
                        netdev_err(dev, "fail read reg 0x1118\n");
-                       return ret;
+                       goto release;
                }
                reg |= BIT(0);
                ret = wilc->hif_func->hif_write_reg(wilc, 0x1118, reg);
                if (!ret) {
                        netdev_err(dev, "fail write reg 0x1118\n");
-                       return ret;
+                       goto release;
                }
                ret = wilc->hif_func->hif_write_reg(wilc, 0xc0000, 0x71);
                if (!ret) {
                        netdev_err(dev, "fail write reg 0xc0000\n");
-                       return ret;
+                       goto release;
                }
        }
 
+release:
        release_bus(wilc, WILC_BUS_RELEASE_ONLY);
 
        return ret;
index 984941e..bd15a56 100644 (file)
@@ -714,7 +714,7 @@ static int __init iscsi_target_init_module(void)
                        sizeof(struct iscsi_queue_req),
                        __alignof__(struct iscsi_queue_req), 0, NULL);
        if (!lio_qr_cache) {
-               pr_err("nable to kmem_cache_create() for"
+               pr_err("Unable to kmem_cache_create() for"
                                " lio_qr_cache\n");
                goto bitmap_out;
        }
index 72016d0..8e7fffb 100644 (file)
@@ -852,6 +852,12 @@ static ssize_t pi_prot_type_store(struct config_item *item,
        return count;
 }
 
+/* always zero, but attr needs to remain RW to avoid userspace breakage */
+static ssize_t pi_prot_format_show(struct config_item *item, char *page)
+{
+       return snprintf(page, PAGE_SIZE, "0\n");
+}
+
 static ssize_t pi_prot_format_store(struct config_item *item,
                const char *page, size_t count)
 {
@@ -1132,7 +1138,7 @@ CONFIGFS_ATTR(, emulate_3pc);
 CONFIGFS_ATTR(, emulate_pr);
 CONFIGFS_ATTR(, pi_prot_type);
 CONFIGFS_ATTR_RO(, hw_pi_prot_type);
-CONFIGFS_ATTR_WO(, pi_prot_format);
+CONFIGFS_ATTR(, pi_prot_format);
 CONFIGFS_ATTR(, pi_prot_verify);
 CONFIGFS_ATTR(, enforce_pr_isids);
 CONFIGFS_ATTR(, is_nonrot);
index 1e6d249..5831e0e 100644 (file)
@@ -148,7 +148,7 @@ struct tcmu_dev {
        size_t ring_size;
 
        struct mutex cmdr_lock;
-       struct list_head cmdr_queue;
+       struct list_head qfull_queue;
 
        uint32_t dbi_max;
        uint32_t dbi_thresh;
@@ -159,6 +159,7 @@ struct tcmu_dev {
 
        struct timer_list cmd_timer;
        unsigned int cmd_time_out;
+       struct list_head inflight_queue;
 
        struct timer_list qfull_timer;
        int qfull_time_out;
@@ -179,7 +180,7 @@ struct tcmu_dev {
 struct tcmu_cmd {
        struct se_cmd *se_cmd;
        struct tcmu_dev *tcmu_dev;
-       struct list_head cmdr_queue_entry;
+       struct list_head queue_entry;
 
        uint16_t cmd_id;
 
@@ -192,6 +193,7 @@ struct tcmu_cmd {
        unsigned long deadline;
 
 #define TCMU_CMD_BIT_EXPIRED 0
+#define TCMU_CMD_BIT_INFLIGHT 1
        unsigned long flags;
 };
 /*
@@ -586,7 +588,7 @@ static struct tcmu_cmd *tcmu_alloc_cmd(struct se_cmd *se_cmd)
        if (!tcmu_cmd)
                return NULL;
 
-       INIT_LIST_HEAD(&tcmu_cmd->cmdr_queue_entry);
+       INIT_LIST_HEAD(&tcmu_cmd->queue_entry);
        tcmu_cmd->se_cmd = se_cmd;
        tcmu_cmd->tcmu_dev = udev;
 
@@ -915,11 +917,13 @@ setup_timer:
                return 0;
 
        tcmu_cmd->deadline = round_jiffies_up(jiffies + msecs_to_jiffies(tmo));
-       mod_timer(timer, tcmu_cmd->deadline);
+       if (!timer_pending(timer))
+               mod_timer(timer, tcmu_cmd->deadline);
+
        return 0;
 }
 
-static int add_to_cmdr_queue(struct tcmu_cmd *tcmu_cmd)
+static int add_to_qfull_queue(struct tcmu_cmd *tcmu_cmd)
 {
        struct tcmu_dev *udev = tcmu_cmd->tcmu_dev;
        unsigned int tmo;
@@ -942,7 +946,7 @@ static int add_to_cmdr_queue(struct tcmu_cmd *tcmu_cmd)
        if (ret)
                return ret;
 
-       list_add_tail(&tcmu_cmd->cmdr_queue_entry, &udev->cmdr_queue);
+       list_add_tail(&tcmu_cmd->queue_entry, &udev->qfull_queue);
        pr_debug("adding cmd %u on dev %s to ring space wait queue\n",
                 tcmu_cmd->cmd_id, udev->name);
        return 0;
@@ -999,7 +1003,7 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
        base_command_size = tcmu_cmd_get_base_cmd_size(tcmu_cmd->dbi_cnt);
        command_size = tcmu_cmd_get_cmd_size(tcmu_cmd, base_command_size);
 
-       if (!list_empty(&udev->cmdr_queue))
+       if (!list_empty(&udev->qfull_queue))
                goto queue;
 
        mb = udev->mb_addr;
@@ -1096,13 +1100,16 @@ static int queue_cmd_ring(struct tcmu_cmd *tcmu_cmd, sense_reason_t *scsi_err)
        UPDATE_HEAD(mb->cmd_head, command_size, udev->cmdr_size);
        tcmu_flush_dcache_range(mb, sizeof(*mb));
 
+       list_add_tail(&tcmu_cmd->queue_entry, &udev->inflight_queue);
+       set_bit(TCMU_CMD_BIT_INFLIGHT, &tcmu_cmd->flags);
+
        /* TODO: only if FLUSH and FUA? */
        uio_event_notify(&udev->uio_info);
 
        return 0;
 
 queue:
-       if (add_to_cmdr_queue(tcmu_cmd)) {
+       if (add_to_qfull_queue(tcmu_cmd)) {
                *scsi_err = TCM_OUT_OF_RESOURCES;
                return -1;
        }
@@ -1145,6 +1152,8 @@ static void tcmu_handle_completion(struct tcmu_cmd *cmd, struct tcmu_cmd_entry *
        if (test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags))
                goto out;
 
+       list_del_init(&cmd->queue_entry);
+
        tcmu_cmd_reset_dbi_cur(cmd);
 
        if (entry->hdr.uflags & TCMU_UFLAG_UNKNOWN_OP) {
@@ -1194,9 +1203,29 @@ out:
        tcmu_free_cmd(cmd);
 }
 
+static void tcmu_set_next_deadline(struct list_head *queue,
+                                  struct timer_list *timer)
+{
+       struct tcmu_cmd *tcmu_cmd, *tmp_cmd;
+       unsigned long deadline = 0;
+
+       list_for_each_entry_safe(tcmu_cmd, tmp_cmd, queue, queue_entry) {
+               if (!time_after(jiffies, tcmu_cmd->deadline)) {
+                       deadline = tcmu_cmd->deadline;
+                       break;
+               }
+       }
+
+       if (deadline)
+               mod_timer(timer, deadline);
+       else
+               del_timer(timer);
+}
+
 static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
 {
        struct tcmu_mailbox *mb;
+       struct tcmu_cmd *cmd;
        int handled = 0;
 
        if (test_bit(TCMU_DEV_BIT_BROKEN, &udev->flags)) {
@@ -1210,7 +1239,6 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
        while (udev->cmdr_last_cleaned != READ_ONCE(mb->cmd_tail)) {
 
                struct tcmu_cmd_entry *entry = (void *) mb + CMDR_OFF + udev->cmdr_last_cleaned;
-               struct tcmu_cmd *cmd;
 
                tcmu_flush_dcache_range(entry, sizeof(*entry));
 
@@ -1243,7 +1271,7 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
                /* no more pending commands */
                del_timer(&udev->cmd_timer);
 
-               if (list_empty(&udev->cmdr_queue)) {
+               if (list_empty(&udev->qfull_queue)) {
                        /*
                         * no more pending or waiting commands so try to
                         * reclaim blocks if needed.
@@ -1252,6 +1280,8 @@ static unsigned int tcmu_handle_completions(struct tcmu_dev *udev)
                            tcmu_global_max_blocks)
                                schedule_delayed_work(&tcmu_unmap_work, 0);
                }
+       } else if (udev->cmd_time_out) {
+               tcmu_set_next_deadline(&udev->inflight_queue, &udev->cmd_timer);
        }
 
        return handled;
@@ -1271,7 +1301,7 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data)
        if (!time_after(jiffies, cmd->deadline))
                return 0;
 
-       is_running = list_empty(&cmd->cmdr_queue_entry);
+       is_running = test_bit(TCMU_CMD_BIT_INFLIGHT, &cmd->flags);
        se_cmd = cmd->se_cmd;
 
        if (is_running) {
@@ -1287,9 +1317,9 @@ static int tcmu_check_expired_cmd(int id, void *p, void *data)
                 * target_complete_cmd will translate this to LUN COMM FAILURE
                 */
                scsi_status = SAM_STAT_CHECK_CONDITION;
+               list_del_init(&cmd->queue_entry);
        } else {
-               list_del_init(&cmd->cmdr_queue_entry);
-
+               list_del_init(&cmd->queue_entry);
                idr_remove(&udev->commands, id);
                tcmu_free_cmd(cmd);
                scsi_status = SAM_STAT_TASK_SET_FULL;
@@ -1372,7 +1402,8 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
 
        INIT_LIST_HEAD(&udev->node);
        INIT_LIST_HEAD(&udev->timedout_entry);
-       INIT_LIST_HEAD(&udev->cmdr_queue);
+       INIT_LIST_HEAD(&udev->qfull_queue);
+       INIT_LIST_HEAD(&udev->inflight_queue);
        idr_init(&udev->commands);
 
        timer_setup(&udev->qfull_timer, tcmu_qfull_timedout, 0);
@@ -1383,7 +1414,7 @@ static struct se_device *tcmu_alloc_device(struct se_hba *hba, const char *name)
        return &udev->se_dev;
 }
 
-static bool run_cmdr_queue(struct tcmu_dev *udev, bool fail)
+static bool run_qfull_queue(struct tcmu_dev *udev, bool fail)
 {
        struct tcmu_cmd *tcmu_cmd, *tmp_cmd;
        LIST_HEAD(cmds);
@@ -1391,15 +1422,15 @@ static bool run_cmdr_queue(struct tcmu_dev *udev, bool fail)
        sense_reason_t scsi_ret;
        int ret;
 
-       if (list_empty(&udev->cmdr_queue))
+       if (list_empty(&udev->qfull_queue))
                return true;
 
        pr_debug("running %s's cmdr queue forcefail %d\n", udev->name, fail);
 
-       list_splice_init(&udev->cmdr_queue, &cmds);
+       list_splice_init(&udev->qfull_queue, &cmds);
 
-       list_for_each_entry_safe(tcmu_cmd, tmp_cmd, &cmds, cmdr_queue_entry) {
-               list_del_init(&tcmu_cmd->cmdr_queue_entry);
+       list_for_each_entry_safe(tcmu_cmd, tmp_cmd, &cmds, queue_entry) {
+               list_del_init(&tcmu_cmd->queue_entry);
 
                pr_debug("removing cmd %u on dev %s from queue\n",
                         tcmu_cmd->cmd_id, udev->name);
@@ -1437,14 +1468,13 @@ static bool run_cmdr_queue(struct tcmu_dev *udev, bool fail)
                         * cmd was requeued, so just put all cmds back in
                         * the queue
                         */
-                       list_splice_tail(&cmds, &udev->cmdr_queue);
+                       list_splice_tail(&cmds, &udev->qfull_queue);
                        drained = false;
-                       goto done;
+                       break;
                }
        }
-       if (list_empty(&udev->cmdr_queue))
-               del_timer(&udev->qfull_timer);
-done:
+
+       tcmu_set_next_deadline(&udev->qfull_queue, &udev->qfull_timer);
        return drained;
 }
 
@@ -1454,7 +1484,7 @@ static int tcmu_irqcontrol(struct uio_info *info, s32 irq_on)
 
        mutex_lock(&udev->cmdr_lock);
        tcmu_handle_completions(udev);
-       run_cmdr_queue(udev, false);
+       run_qfull_queue(udev, false);
        mutex_unlock(&udev->cmdr_lock);
 
        return 0;
@@ -1982,7 +2012,7 @@ static void tcmu_block_dev(struct tcmu_dev *udev)
        /* complete IO that has executed successfully */
        tcmu_handle_completions(udev);
        /* fail IO waiting to be queued */
-       run_cmdr_queue(udev, true);
+       run_qfull_queue(udev, true);
 
 unlock:
        mutex_unlock(&udev->cmdr_lock);
@@ -1997,7 +2027,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level)
        mutex_lock(&udev->cmdr_lock);
 
        idr_for_each_entry(&udev->commands, cmd, i) {
-               if (!list_empty(&cmd->cmdr_queue_entry))
+               if (!test_bit(TCMU_CMD_BIT_INFLIGHT, &cmd->flags))
                        continue;
 
                pr_debug("removing cmd %u on dev %s from ring (is expired %d)\n",
@@ -2006,6 +2036,7 @@ static void tcmu_reset_ring(struct tcmu_dev *udev, u8 err_level)
 
                idr_remove(&udev->commands, i);
                if (!test_bit(TCMU_CMD_BIT_EXPIRED, &cmd->flags)) {
+                       list_del_init(&cmd->queue_entry);
                        if (err_level == 1) {
                                /*
                                 * Userspace was not able to start the
@@ -2666,6 +2697,10 @@ static void check_timedout_devices(void)
 
                mutex_lock(&udev->cmdr_lock);
                idr_for_each(&udev->commands, tcmu_check_expired_cmd, NULL);
+
+               tcmu_set_next_deadline(&udev->inflight_queue, &udev->cmd_timer);
+               tcmu_set_next_deadline(&udev->qfull_queue, &udev->qfull_timer);
+
                mutex_unlock(&udev->cmdr_lock);
 
                spin_lock_bh(&timed_out_udevs_lock);
index dfd2324..6fff161 100644 (file)
@@ -774,7 +774,7 @@ of_cpufreq_cooling_register(struct cpufreq_policy *policy)
 
                cdev = __cpufreq_cooling_register(np, policy, capacitance);
                if (IS_ERR(cdev)) {
-                       pr_err("cpu_cooling: cpu%d is not running as cooling device: %ld\n",
+                       pr_err("cpu_cooling: cpu%d failed to register as cooling device: %ld\n",
                               policy->cpu, PTR_ERR(cdev));
                        cdev = NULL;
                }
index 0582bd1..0ca908d 100644 (file)
@@ -4,7 +4,7 @@
 
 config INT340X_THERMAL
        tristate "ACPI INT340X thermal drivers"
-       depends on X86 && ACPI
+       depends on X86 && ACPI && PCI
        select THERMAL_GOV_USER_SPACE
        select ACPI_THERMAL_REL
        select ACPI_FAN
index 284cf2c..8e1cf4d 100644 (file)
@@ -84,7 +84,12 @@ static ssize_t power_limit_##index##_##suffix##_show(struct device *dev, \
        struct pci_dev *pci_dev; \
        struct platform_device *pdev; \
        struct proc_thermal_device *proc_dev; \
-\
+       \
+       if (proc_thermal_emum_mode == PROC_THERMAL_NONE) { \
+               dev_warn(dev, "Attempted to get power limit before device was initialized!\n"); \
+               return 0; \
+       } \
+       \
        if (proc_thermal_emum_mode == PROC_THERMAL_PLATFORM_DEV) { \
                pdev = to_platform_device(dev); \
                proc_dev = platform_get_drvdata(pdev); \
@@ -298,11 +303,6 @@ static int proc_thermal_add(struct device *dev,
        *priv = proc_priv;
 
        ret = proc_thermal_read_ppcc(proc_priv);
-       if (!ret) {
-               ret = sysfs_create_group(&dev->kobj,
-                                        &power_limit_attribute_group);
-
-       }
        if (ret)
                return ret;
 
@@ -316,8 +316,7 @@ static int proc_thermal_add(struct device *dev,
 
        proc_priv->int340x_zone = int340x_thermal_zone_add(adev, ops);
        if (IS_ERR(proc_priv->int340x_zone)) {
-               ret = PTR_ERR(proc_priv->int340x_zone);
-               goto remove_group;
+               return PTR_ERR(proc_priv->int340x_zone);
        } else
                ret = 0;
 
@@ -331,9 +330,6 @@ static int proc_thermal_add(struct device *dev,
 
 remove_zone:
        int340x_thermal_zone_remove(proc_priv->int340x_zone);
-remove_group:
-       sysfs_remove_group(&proc_priv->dev->kobj,
-                          &power_limit_attribute_group);
 
        return ret;
 }
@@ -364,7 +360,10 @@ static int int3401_add(struct platform_device *pdev)
        platform_set_drvdata(pdev, proc_priv);
        proc_thermal_emum_mode = PROC_THERMAL_PLATFORM_DEV;
 
-       return 0;
+       dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PLATFORM_DEV\n");
+
+       return sysfs_create_group(&pdev->dev.kobj,
+                                        &power_limit_attribute_group);
 }
 
 static int int3401_remove(struct platform_device *pdev)
@@ -423,7 +422,7 @@ static int  proc_thermal_pci_probe(struct pci_dev *pdev,
                proc_priv->soc_dts = intel_soc_dts_iosf_init(
                                        INTEL_SOC_DTS_INTERRUPT_MSI, 2, 0);
 
-               if (proc_priv->soc_dts && pdev->irq) {
+               if (!IS_ERR(proc_priv->soc_dts) && pdev->irq) {
                        ret = pci_enable_msi(pdev);
                        if (!ret) {
                                ret = request_threaded_irq(pdev->irq, NULL,
@@ -441,7 +440,10 @@ static int  proc_thermal_pci_probe(struct pci_dev *pdev,
                        dev_err(&pdev->dev, "No auxiliary DTSs enabled\n");
        }
 
-       return 0;
+       dev_info(&pdev->dev, "Creating sysfs group for PROC_THERMAL_PCI\n");
+
+       return sysfs_create_group(&pdev->dev.kobj,
+                                        &power_limit_attribute_group);
 }
 
 static void  proc_thermal_pci_remove(struct pci_dev *pdev)
index 4bfdb4a..2df059c 100644 (file)
@@ -867,14 +867,14 @@ __init *thermal_of_build_thermal_zone(struct device_node *np)
 
        ret = of_property_read_u32(np, "polling-delay-passive", &prop);
        if (ret < 0) {
-               pr_err("missing polling-delay-passive property\n");
+               pr_err("%pOFn: missing polling-delay-passive property\n", np);
                goto free_tz;
        }
        tz->passive_delay = prop;
 
        ret = of_property_read_u32(np, "polling-delay", &prop);
        if (ret < 0) {
-               pr_err("missing polling-delay property\n");
+               pr_err("%pOFn: missing polling-delay property\n", np);
                goto free_tz;
        }
        tz->polling_delay = prop;
index 4164414..8bdf42b 100644 (file)
@@ -597,6 +597,7 @@ static ssize_t n_hdlc_tty_read(struct tty_struct *tty, struct file *file,
                                /* too large for caller's buffer */
                                ret = -EOVERFLOW;
                        } else {
+                               __set_current_state(TASK_RUNNING);
                                if (copy_to_user(buf, rbuf->buf, rbuf->count))
                                        ret = -EFAULT;
                                else
index 189ab12..e441221 100644 (file)
@@ -1070,15 +1070,16 @@ int serial8250_register_8250_port(struct uart_8250_port *up)
 
                        ret = 0;
                }
-       }
 
-       /* Initialise interrupt backoff work if required */
-       if (up->overrun_backoff_time_ms > 0) {
-               uart->overrun_backoff_time_ms = up->overrun_backoff_time_ms;
-               INIT_DELAYED_WORK(&uart->overrun_backoff,
-                                 serial_8250_overrun_backoff_work);
-       } else {
-               uart->overrun_backoff_time_ms = 0;
+               /* Initialise interrupt backoff work if required */
+               if (up->overrun_backoff_time_ms > 0) {
+                       uart->overrun_backoff_time_ms =
+                               up->overrun_backoff_time_ms;
+                       INIT_DELAYED_WORK(&uart->overrun_backoff,
+                                       serial_8250_overrun_backoff_work);
+               } else {
+                       uart->overrun_backoff_time_ms = 0;
+               }
        }
 
        mutex_unlock(&serial_mutex);
index e2c4076..c1fdbc0 100644 (file)
@@ -357,6 +357,9 @@ static int mtk8250_probe_of(struct platform_device *pdev, struct uart_port *p,
        if (dmacnt == 2) {
                data->dma = devm_kzalloc(&pdev->dev, sizeof(*data->dma),
                                         GFP_KERNEL);
+               if (!data->dma)
+                       return -ENOMEM;
+
                data->dma->fn = mtk8250_dma_filter;
                data->dma->rx_size = MTK_UART_RX_SIZE;
                data->dma->rxconf.src_maxburst = MTK_UART_RX_TRIGGER;
index f80a300..48bd694 100644 (file)
@@ -3420,6 +3420,11 @@ static int
 serial_pci_guess_board(struct pci_dev *dev, struct pciserial_board *board)
 {
        int num_iomem, num_port, first_port = -1, i;
+       int rc;
+
+       rc = serial_pci_is_class_communication(dev);
+       if (rc)
+               return rc;
 
        /*
         * Should we try to make guesses for multiport serial devices later?
@@ -3647,10 +3652,6 @@ pciserial_init_one(struct pci_dev *dev, const struct pci_device_id *ent)
 
        board = &pci_boards[ent->driver_data];
 
-       rc = serial_pci_is_class_communication(dev);
-       if (rc)
-               return rc;
-
        rc = serial_pci_is_blacklisted(dev);
        if (rc)
                return rc;
index 67b9bf3..089a6f2 100644 (file)
@@ -85,6 +85,18 @@ config SERIAL_EARLYCON_ARM_SEMIHOST
          with "earlycon=smh" on the kernel command line. The console is
          enabled when early_param is processed.
 
+config SERIAL_EARLYCON_RISCV_SBI
+       bool "Early console using RISC-V SBI"
+       depends on RISCV
+       select SERIAL_CORE
+       select SERIAL_CORE_CONSOLE
+       select SERIAL_EARLYCON
+       help
+         Support for early debug console using RISC-V SBI. This enables
+         the console before standard serial driver is probed. This is enabled
+         with "earlycon=sbi" on the kernel command line. The console is
+         enabled when early_param is processed.
+
 config SERIAL_SB1250_DUART
        tristate "BCM1xxx on-chip DUART serial support"
        depends on SIBYTE_SB1xxx_SOC=y
index 8c30373..1511e8a 100644 (file)
@@ -7,6 +7,7 @@ obj-$(CONFIG_SERIAL_CORE) += serial_core.o
 
 obj-$(CONFIG_SERIAL_EARLYCON) += earlycon.o
 obj-$(CONFIG_SERIAL_EARLYCON_ARM_SEMIHOST) += earlycon-arm-semihost.o
+obj-$(CONFIG_SERIAL_EARLYCON_RISCV_SBI) += earlycon-riscv-sbi.o
 
 # These Sparc drivers have to appear before others such as 8250
 # which share ttySx minor node space.  Otherwise console device
diff --git a/drivers/tty/serial/earlycon-riscv-sbi.c b/drivers/tty/serial/earlycon-riscv-sbi.c
new file mode 100644 (file)
index 0000000..ce81523
--- /dev/null
@@ -0,0 +1,31 @@
+// SPDX-License-Identifier: GPL-2.0
+/*
+ * RISC-V SBI based earlycon
+ *
+ * Copyright (C) 2018 Anup Patel <anup@brainfault.org>
+ */
+#include <linux/kernel.h>
+#include <linux/console.h>
+#include <linux/init.h>
+#include <linux/serial_core.h>
+#include <asm/sbi.h>
+
+static void sbi_putc(struct uart_port *port, int c)
+{
+       sbi_console_putchar(c);
+}
+
+static void sbi_console_write(struct console *con,
+                             const char *s, unsigned n)
+{
+       struct earlycon_device *dev = con->data;
+       uart_console_write(&dev->port, s, n, sbi_putc);
+}
+
+static int __init early_sbi_setup(struct earlycon_device *device,
+                                 const char *opt)
+{
+       device->con->write = sbi_console_write;
+       return 0;
+}
+EARLYCON_DECLARE(sbi, early_sbi_setup);
index 241a48e..debdd1b 100644 (file)
@@ -1697,7 +1697,7 @@ lpuart32_set_termios(struct uart_port *port, struct ktermios *termios,
        }
 
        /* ask the core to calculate the divisor */
-       baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 16);
+       baud = uart_get_baud_rate(port, termios, old, 50, port->uartclk / 4);
 
        spin_lock_irqsave(&sport->port.lock, flags);
 
index e052b69..9de9f0f 100644 (file)
@@ -114,9 +114,9 @@ struct ltq_uart_port {
 
 static inline void asc_update_bits(u32 clear, u32 set, void __iomem *reg)
 {
-       u32 tmp = readl(reg);
+       u32 tmp = __raw_readl(reg);
 
-       writel((tmp & ~clear) | set, reg);
+       __raw_writel((tmp & ~clear) | set, reg);
 }
 
 static inline struct
@@ -144,7 +144,7 @@ lqasc_start_tx(struct uart_port *port)
 static void
 lqasc_stop_rx(struct uart_port *port)
 {
-       writel(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
+       __raw_writel(ASCWHBSTATE_CLRREN, port->membase + LTQ_ASC_WHBSTATE);
 }
 
 static int
@@ -153,11 +153,12 @@ lqasc_rx_chars(struct uart_port *port)
        struct tty_port *tport = &port->state->port;
        unsigned int ch = 0, rsr = 0, fifocnt;
 
-       fifocnt = readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_RXFFLMASK;
+       fifocnt = __raw_readl(port->membase + LTQ_ASC_FSTAT) &
+                 ASCFSTAT_RXFFLMASK;
        while (fifocnt--) {
                u8 flag = TTY_NORMAL;
                ch = readb(port->membase + LTQ_ASC_RBUF);
-               rsr = (readl(port->membase + LTQ_ASC_STATE)
+               rsr = (__raw_readl(port->membase + LTQ_ASC_STATE)
                        & ASCSTATE_ANY) | UART_DUMMY_UER_RX;
                tty_flip_buffer_push(tport);
                port->icount.rx++;
@@ -217,7 +218,7 @@ lqasc_tx_chars(struct uart_port *port)
                return;
        }
 
-       while (((readl(port->membase + LTQ_ASC_FSTAT) &
+       while (((__raw_readl(port->membase + LTQ_ASC_FSTAT) &
                ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF) != 0) {
                if (port->x_char) {
                        writeb(port->x_char, port->membase + LTQ_ASC_TBUF);
@@ -245,7 +246,7 @@ lqasc_tx_int(int irq, void *_port)
        unsigned long flags;
        struct uart_port *port = (struct uart_port *)_port;
        spin_lock_irqsave(&ltq_asc_lock, flags);
-       writel(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR);
+       __raw_writel(ASC_IRNCR_TIR, port->membase + LTQ_ASC_IRNCR);
        spin_unlock_irqrestore(&ltq_asc_lock, flags);
        lqasc_start_tx(port);
        return IRQ_HANDLED;
@@ -270,7 +271,7 @@ lqasc_rx_int(int irq, void *_port)
        unsigned long flags;
        struct uart_port *port = (struct uart_port *)_port;
        spin_lock_irqsave(&ltq_asc_lock, flags);
-       writel(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR);
+       __raw_writel(ASC_IRNCR_RIR, port->membase + LTQ_ASC_IRNCR);
        lqasc_rx_chars(port);
        spin_unlock_irqrestore(&ltq_asc_lock, flags);
        return IRQ_HANDLED;
@@ -280,7 +281,8 @@ static unsigned int
 lqasc_tx_empty(struct uart_port *port)
 {
        int status;
-       status = readl(port->membase + LTQ_ASC_FSTAT) & ASCFSTAT_TXFFLMASK;
+       status = __raw_readl(port->membase + LTQ_ASC_FSTAT) &
+                ASCFSTAT_TXFFLMASK;
        return status ? 0 : TIOCSER_TEMT;
 }
 
@@ -313,12 +315,12 @@ lqasc_startup(struct uart_port *port)
        asc_update_bits(ASCCLC_DISS | ASCCLC_RMCMASK, (1 << ASCCLC_RMCOFFSET),
                port->membase + LTQ_ASC_CLC);
 
-       writel(0, port->membase + LTQ_ASC_PISEL);
-       writel(
+       __raw_writel(0, port->membase + LTQ_ASC_PISEL);
+       __raw_writel(
                ((TXFIFO_FL << ASCTXFCON_TXFITLOFF) & ASCTXFCON_TXFITLMASK) |
                ASCTXFCON_TXFEN | ASCTXFCON_TXFFLU,
                port->membase + LTQ_ASC_TXFCON);
-       writel(
+       __raw_writel(
                ((RXFIFO_FL << ASCRXFCON_RXFITLOFF) & ASCRXFCON_RXFITLMASK)
                | ASCRXFCON_RXFEN | ASCRXFCON_RXFFLU,
                port->membase + LTQ_ASC_RXFCON);
@@ -350,7 +352,7 @@ lqasc_startup(struct uart_port *port)
                goto err2;
        }
 
-       writel(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX,
+       __raw_writel(ASC_IRNREN_RX | ASC_IRNREN_ERR | ASC_IRNREN_TX,
                port->membase + LTQ_ASC_IRNREN);
        return 0;
 
@@ -369,7 +371,7 @@ lqasc_shutdown(struct uart_port *port)
        free_irq(ltq_port->rx_irq, port);
        free_irq(ltq_port->err_irq, port);
 
-       writel(0, port->membase + LTQ_ASC_CON);
+       __raw_writel(0, port->membase + LTQ_ASC_CON);
        asc_update_bits(ASCRXFCON_RXFEN, ASCRXFCON_RXFFLU,
                port->membase + LTQ_ASC_RXFCON);
        asc_update_bits(ASCTXFCON_TXFEN, ASCTXFCON_TXFFLU,
@@ -461,13 +463,13 @@ lqasc_set_termios(struct uart_port *port,
        asc_update_bits(ASCCON_BRS, 0, port->membase + LTQ_ASC_CON);
 
        /* now we can write the new baudrate into the register */
-       writel(divisor, port->membase + LTQ_ASC_BG);
+       __raw_writel(divisor, port->membase + LTQ_ASC_BG);
 
        /* turn the baudrate generator back on */
        asc_update_bits(0, ASCCON_R, port->membase + LTQ_ASC_CON);
 
        /* enable rx */
-       writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
+       __raw_writel(ASCWHBSTATE_SETREN, port->membase + LTQ_ASC_WHBSTATE);
 
        spin_unlock_irqrestore(&ltq_asc_lock, flags);
 
@@ -578,7 +580,7 @@ lqasc_console_putchar(struct uart_port *port, int ch)
                return;
 
        do {
-               fifofree = (readl(port->membase + LTQ_ASC_FSTAT)
+               fifofree = (__raw_readl(port->membase + LTQ_ASC_FSTAT)
                        & ASCFSTAT_TXFREEMASK) >> ASCFSTAT_TXFREEOFF;
        } while (fifofree == 0);
        writeb(ch, port->membase + LTQ_ASC_TBUF);
index a72d6d9..3801660 100644 (file)
@@ -225,7 +225,7 @@ static unsigned int qcom_geni_serial_get_mctrl(struct uart_port *uport)
        unsigned int mctrl = TIOCM_DSR | TIOCM_CAR;
        u32 geni_ios;
 
-       if (uart_console(uport) || !uart_cts_enabled(uport)) {
+       if (uart_console(uport)) {
                mctrl |= TIOCM_CTS;
        } else {
                geni_ios = readl_relaxed(uport->membase + SE_GENI_IOS);
@@ -241,7 +241,7 @@ static void qcom_geni_serial_set_mctrl(struct uart_port *uport,
 {
        u32 uart_manual_rfr = 0;
 
-       if (uart_console(uport) || !uart_cts_enabled(uport))
+       if (uart_console(uport))
                return;
 
        if (!(mctrl & TIOCM_RTS))
index d4cca5b..556f50a 100644 (file)
@@ -130,6 +130,9 @@ static void uart_start(struct tty_struct *tty)
        struct uart_port *port;
        unsigned long flags;
 
+       if (!state)
+               return;
+
        port = uart_port_lock(state, flags);
        __uart_start(tty);
        uart_port_unlock(port, flags);
@@ -550,10 +553,12 @@ static int uart_put_char(struct tty_struct *tty, unsigned char c)
        int ret = 0;
 
        circ = &state->xmit;
-       if (!circ->buf)
+       port = uart_port_lock(state, flags);
+       if (!circ->buf) {
+               uart_port_unlock(port, flags);
                return 0;
+       }
 
-       port = uart_port_lock(state, flags);
        if (port && uart_circ_chars_free(circ) != 0) {
                circ->buf[circ->head] = c;
                circ->head = (circ->head + 1) & (UART_XMIT_SIZE - 1);
@@ -586,11 +591,13 @@ static int uart_write(struct tty_struct *tty,
                return -EL3HLT;
        }
 
+       port = uart_port_lock(state, flags);
        circ = &state->xmit;
-       if (!circ->buf)
+       if (!circ->buf) {
+               uart_port_unlock(port, flags);
                return 0;
+       }
 
-       port = uart_port_lock(state, flags);
        while (port) {
                c = CIRC_SPACE_TO_END(circ->head, circ->tail, UART_XMIT_SIZE);
                if (count < c)
@@ -723,6 +730,9 @@ static void uart_unthrottle(struct tty_struct *tty)
        upstat_t mask = UPSTAT_SYNC_FIFO;
        struct uart_port *port;
 
+       if (!state)
+               return;
+
        port = uart_port_ref(state);
        if (!port)
                return;
index 8df0fd8..64bbeb7 100644 (file)
@@ -1921,7 +1921,7 @@ out_nomem:
 
 static void sci_free_irq(struct sci_port *port)
 {
-       int i;
+       int i, j;
 
        /*
         * Intentionally in reverse order so we iterate over the muxed
@@ -1937,6 +1937,13 @@ static void sci_free_irq(struct sci_port *port)
                if (unlikely(irq < 0))
                        continue;
 
+               /* Check if already freed (irq was muxed) */
+               for (j = 0; j < i; j++)
+                       if (port->irqs[j] == irq)
+                               j = i + 1;
+               if (j > i)
+                       continue;
+
                free_irq(port->irqs[i], port);
                kfree(port->irqstr[i]);
 
index bfe9ad8..21ffcce 100644 (file)
@@ -1256,7 +1256,8 @@ static void tty_driver_remove_tty(struct tty_driver *driver, struct tty_struct *
 static int tty_reopen(struct tty_struct *tty)
 {
        struct tty_driver *driver = tty->driver;
-       int retval;
+       struct tty_ldisc *ld;
+       int retval = 0;
 
        if (driver->type == TTY_DRIVER_TYPE_PTY &&
            driver->subtype == PTY_TYPE_MASTER)
@@ -1268,13 +1269,18 @@ static int tty_reopen(struct tty_struct *tty)
        if (test_bit(TTY_EXCLUSIVE, &tty->flags) && !capable(CAP_SYS_ADMIN))
                return -EBUSY;
 
-       retval = tty_ldisc_lock(tty, 5 * HZ);
-       if (retval)
-               return retval;
+       ld = tty_ldisc_ref_wait(tty);
+       if (ld) {
+               tty_ldisc_deref(ld);
+       } else {
+               retval = tty_ldisc_lock(tty, 5 * HZ);
+               if (retval)
+                       return retval;
 
-       if (!tty->ldisc)
-               retval = tty_ldisc_reinit(tty, tty->termios.c_line);
-       tty_ldisc_unlock(tty);
+               if (!tty->ldisc)
+                       retval = tty_ldisc_reinit(tty, tty->termios.c_line);
+               tty_ldisc_unlock(tty);
+       }
 
        if (retval == 0)
                tty->count++;
@@ -2183,7 +2189,8 @@ static int tiocsti(struct tty_struct *tty, char __user *p)
        ld = tty_ldisc_ref_wait(tty);
        if (!ld)
                return -EIO;
-       ld->ops->receive_buf(tty, &ch, &mbz, 1);
+       if (ld->ops->receive_buf)
+               ld->ops->receive_buf(tty, &ch, &mbz, 1);
        tty_ldisc_deref(ld);
        return 0;
 }
index 41ec8e5..bba7556 100644 (file)
@@ -1272,6 +1272,7 @@ static int vc_do_resize(struct tty_struct *tty, struct vc_data *vc,
        if (con_is_visible(vc))
                update_screen(vc);
        vt_event_post(VT_EVENT_RESIZE, vc->vc_num, vc->vc_num);
+       notify_update(vc);
        return err;
 }
 
@@ -2764,8 +2765,8 @@ rescan_last_byte:
        con_flush(vc, draw_from, draw_to, &draw_x);
        vc_uniscr_debug_check(vc);
        console_conditional_schedule();
-       console_unlock();
        notify_update(vc);
+       console_unlock();
        return n;
 }
 
@@ -2884,8 +2885,7 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
        unsigned char c;
        static DEFINE_SPINLOCK(printing_lock);
        const ushort *start;
-       ushort cnt = 0;
-       ushort myx;
+       ushort start_x, cnt;
        int kmsg_console;
 
        /* console busy or not yet initialized */
@@ -2898,10 +2898,6 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
        if (kmsg_console && vc_cons_allocated(kmsg_console - 1))
                vc = vc_cons[kmsg_console - 1].d;
 
-       /* read `x' only after setting currcons properly (otherwise
-          the `x' macro will read the x of the foreground console). */
-       myx = vc->vc_x;
-
        if (!vc_cons_allocated(fg_console)) {
                /* impossible */
                /* printk("vt_console_print: tty %d not allocated ??\n", currcons+1); */
@@ -2916,53 +2912,41 @@ static void vt_console_print(struct console *co, const char *b, unsigned count)
                hide_cursor(vc);
 
        start = (ushort *)vc->vc_pos;
-
-       /* Contrived structure to try to emulate original need_wrap behaviour
-        * Problems caused when we have need_wrap set on '\n' character */
+       start_x = vc->vc_x;
+       cnt = 0;
        while (count--) {
                c = *b++;
                if (c == 10 || c == 13 || c == 8 || vc->vc_need_wrap) {
-                       if (cnt > 0) {
-                               if (con_is_visible(vc))
-                                       vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
-                               vc->vc_x += cnt;
-                               if (vc->vc_need_wrap)
-                                       vc->vc_x--;
-                               cnt = 0;
-                       }
+                       if (cnt && con_is_visible(vc))
+                               vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x);
+                       cnt = 0;
                        if (c == 8) {           /* backspace */
                                bs(vc);
                                start = (ushort *)vc->vc_pos;
-                               myx = vc->vc_x;
+                               start_x = vc->vc_x;
                                continue;
                        }
                        if (c != 13)
                                lf(vc);
                        cr(vc);
                        start = (ushort *)vc->vc_pos;
-                       myx = vc->vc_x;
+                       start_x = vc->vc_x;
                        if (c == 10 || c == 13)
                                continue;
                }
+               vc_uniscr_putc(vc, c);
                scr_writew((vc->vc_attr << 8) + c, (unsigned short *)vc->vc_pos);
                notify_write(vc, c);
                cnt++;
-               if (myx == vc->vc_cols - 1) {
-                       vc->vc_need_wrap = 1;
-                       continue;
-               }
-               vc->vc_pos += 2;
-               myx++;
-       }
-       if (cnt > 0) {
-               if (con_is_visible(vc))
-                       vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, vc->vc_x);
-               vc->vc_x += cnt;
-               if (vc->vc_x == vc->vc_cols) {
-                       vc->vc_x--;
+               if (vc->vc_x == vc->vc_cols - 1) {
                        vc->vc_need_wrap = 1;
+               } else {
+                       vc->vc_pos += 2;
+                       vc->vc_x++;
                }
        }
+       if (cnt && con_is_visible(vc))
+               vc->vc_sw->con_putcs(vc, start, cnt, vc->vc_y, start_x);
        set_cursor(vc);
        notify_update(vc);
 
index e81de9c..9b45aa4 100644 (file)
@@ -316,7 +316,8 @@ static int ci_hdrc_imx_probe(struct platform_device *pdev)
        if (IS_ERR(data->usbmisc_data))
                return PTR_ERR(data->usbmisc_data);
 
-       if (of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC) {
+       if ((of_usb_get_phy_mode(dev->of_node) == USBPHY_INTERFACE_MODE_HSIC)
+               && data->usbmisc_data) {
                pdata.flags |= CI_HDRC_IMX_IS_HSIC;
                data->usbmisc_data->hsic = 1;
                data->pinctrl = devm_pinctrl_get(dev);
index ed8c62b..739f896 100644 (file)
@@ -1865,6 +1865,13 @@ static const struct usb_device_id acm_ids[] = {
        .driver_info = IGNORE_DEVICE,
        },
 
+       { USB_DEVICE(0x1bc7, 0x0021), /* Telit 3G ACM only composition */
+       .driver_info = SEND_ZERO_PACKET,
+       },
+       { USB_DEVICE(0x1bc7, 0x0023), /* Telit 3G ACM + ECM composition */
+       .driver_info = SEND_ZERO_PACKET,
+       },
+
        /* control interfaces without any protocol set */
        { USB_INTERFACE_INFO(USB_CLASS_COMM, USB_CDC_SUBCLASS_ACM,
                USB_CDC_PROTO_NONE) },
index 356b05c..f713cec 100644 (file)
@@ -143,9 +143,12 @@ int usb_choose_configuration(struct usb_device *udev)
                        continue;
                }
 
-               if (i > 0 && desc && is_audio(desc) && is_uac3_config(desc)) {
-                       best = c;
-                       break;
+               if (i > 0 && desc && is_audio(desc)) {
+                       if (is_uac3_config(desc)) {
+                               best = c;
+                               break;
+                       }
+                       continue;
                }
 
                /* From the remaining configs, choose the first one whose
index dc7f7fd..c12ac56 100644 (file)
@@ -119,11 +119,6 @@ static const struct attribute_group ports_group = {
        .attrs = ports_attrs,
 };
 
-static const struct attribute_group *ports_groups[] = {
-       &ports_group,
-       NULL
-};
-
 /***************************************
  * Adding & removing ports
  ***************************************/
@@ -307,6 +302,7 @@ static int usbport_trig_notify(struct notifier_block *nb, unsigned long action,
 static int usbport_trig_activate(struct led_classdev *led_cdev)
 {
        struct usbport_trig_data *usbport_data;
+       int err;
 
        usbport_data = kzalloc(sizeof(*usbport_data), GFP_KERNEL);
        if (!usbport_data)
@@ -315,6 +311,9 @@ static int usbport_trig_activate(struct led_classdev *led_cdev)
 
        /* List of ports */
        INIT_LIST_HEAD(&usbport_data->ports);
+       err = sysfs_create_group(&led_cdev->dev->kobj, &ports_group);
+       if (err)
+               goto err_free;
        usb_for_each_dev(usbport_data, usbport_trig_add_usb_dev_ports);
        usbport_trig_update_count(usbport_data);
 
@@ -322,8 +321,11 @@ static int usbport_trig_activate(struct led_classdev *led_cdev)
        usbport_data->nb.notifier_call = usbport_trig_notify;
        led_set_trigger_data(led_cdev, usbport_data);
        usb_register_notify(&usbport_data->nb);
-
        return 0;
+
+err_free:
+       kfree(usbport_data);
+       return err;
 }
 
 static void usbport_trig_deactivate(struct led_classdev *led_cdev)
@@ -335,6 +337,8 @@ static void usbport_trig_deactivate(struct led_classdev *led_cdev)
                usbport_trig_remove_port(usbport_data, port);
        }
 
+       sysfs_remove_group(&led_cdev->dev->kobj, &ports_group);
+
        usb_unregister_notify(&usbport_data->nb);
 
        kfree(usbport_data);
@@ -344,7 +348,6 @@ static struct led_trigger usbport_led_trigger = {
        .name     = "usbport",
        .activate = usbport_trig_activate,
        .deactivate = usbport_trig_deactivate,
-       .groups = ports_groups,
 };
 
 static int __init usbport_trig_init(void)
index 514c521..8bc35d5 100644 (file)
@@ -394,7 +394,8 @@ static const struct usb_device_id usb_quirk_list[] = {
        { USB_DEVICE(0x1a40, 0x0101), .driver_info = USB_QUIRK_HUB_SLOW_RESET },
 
        /* Corsair K70 RGB */
-       { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT },
+       { USB_DEVICE(0x1b1c, 0x1b13), .driver_info = USB_QUIRK_DELAY_INIT |
+         USB_QUIRK_DELAY_CTRL_MSG },
 
        /* Corsair Strafe */
        { USB_DEVICE(0x1b1c, 0x1b15), .driver_info = USB_QUIRK_DELAY_INIT |
index 68ad75a..55ef3cc 100644 (file)
@@ -261,7 +261,7 @@ static void dwc2_gadget_wkup_alert_handler(struct dwc2_hsotg *hsotg)
 
        if (gintsts2 & GINTSTS2_WKUP_ALERT_INT) {
                dev_dbg(hsotg->dev, "%s: Wkup_Alert_Int\n", __func__);
-               dwc2_clear_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT);
+               dwc2_set_bit(hsotg, GINTSTS2, GINTSTS2_WKUP_ALERT_INT);
                dwc2_set_bit(hsotg, DCTL, DCTL_RMTWKUPSIG);
        }
 }
index cb7fcd7..c1e9ea6 100644 (file)
@@ -78,7 +78,7 @@ static int dwc3_exynos_probe(struct platform_device *pdev)
        for (i = 0; i < exynos->num_clks; i++) {
                ret = clk_prepare_enable(exynos->clks[i]);
                if (ret) {
-                       while (--i > 0)
+                       while (i-- > 0)
                                clk_disable_unprepare(exynos->clks[i]);
                        return ret;
                }
@@ -223,7 +223,7 @@ static int dwc3_exynos_resume(struct device *dev)
        for (i = 0; i < exynos->num_clks; i++) {
                ret = clk_prepare_enable(exynos->clks[i]);
                if (ret) {
-                       while (--i > 0)
+                       while (i-- > 0)
                                clk_disable_unprepare(exynos->clks[i]);
                        return ret;
                }
index 07bd31b..6c9b76b 100644 (file)
@@ -177,6 +177,7 @@ static void dwc3_gadget_del_and_unmap_request(struct dwc3_ep *dep,
        req->started = false;
        list_del(&req->list);
        req->remaining = 0;
+       req->needs_extra_trb = false;
 
        if (req->request.status == -EINPROGRESS)
                req->request.status = status;
@@ -1118,7 +1119,7 @@ static void dwc3_prepare_one_trb_linear(struct dwc3_ep *dep,
        unsigned int maxp = usb_endpoint_maxp(dep->endpoint.desc);
        unsigned int rem = length % maxp;
 
-       if (rem && usb_endpoint_dir_out(dep->endpoint.desc)) {
+       if ((!length || rem) && usb_endpoint_dir_out(dep->endpoint.desc)) {
                struct dwc3     *dwc = dep->dwc;
                struct dwc3_trb *trb;
 
@@ -1984,6 +1985,7 @@ static int __dwc3_gadget_start(struct dwc3 *dwc)
 
        /* begin to receive SETUP packets */
        dwc->ep0state = EP0_SETUP_PHASE;
+       dwc->link_state = DWC3_LINK_STATE_SS_DIS;
        dwc3_ep0_out_start(dwc);
 
        dwc3_gadget_enable_irq(dwc);
@@ -3379,6 +3381,8 @@ int dwc3_gadget_suspend(struct dwc3 *dwc)
        dwc3_disconnect_gadget(dwc);
        __dwc3_gadget_stop(dwc);
 
+       synchronize_irq(dwc->irq_gadget);
+
        return 0;
 }
 
index 9cdef10..ed68a48 100644 (file)
@@ -838,7 +838,7 @@ static struct usb_function *source_sink_alloc_func(
 
        ss = kzalloc(sizeof(*ss), GFP_KERNEL);
        if (!ss)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        ss_opts =  container_of(fi, struct f_ss_opts, func_inst);
 
index 01b44e1..ccbd1d3 100644 (file)
@@ -172,8 +172,9 @@ static int scratchpad_setup(struct bdc *bdc)
        /* Refer to BDC spec, Table 4 for description of SPB */
        sp_buff_size = 1 << (sp_buff_size + 5);
        dev_dbg(bdc->dev, "Allocating %d bytes for scratchpad\n", sp_buff_size);
-       bdc->scratchpad.buff  =  dma_zalloc_coherent(bdc->dev, sp_buff_size,
-                                       &bdc->scratchpad.sp_dma, GFP_KERNEL);
+       bdc->scratchpad.buff  =  dma_alloc_coherent(bdc->dev, sp_buff_size,
+                                                   &bdc->scratchpad.sp_dma,
+                                                   GFP_KERNEL);
 
        if (!bdc->scratchpad.buff)
                goto fail;
@@ -202,11 +203,9 @@ static int setup_srr(struct bdc *bdc, int interrupter)
        bdc_writel(bdc->regs, BDC_SRRINT(0), BDC_SRR_RWS | BDC_SRR_RST);
        bdc->srr.dqp_index = 0;
        /* allocate the status report descriptors */
-       bdc->srr.sr_bds = dma_zalloc_coherent(
-                                       bdc->dev,
-                                       NUM_SR_ENTRIES * sizeof(struct bdc_bd),
-                                       &bdc->srr.dma_addr,
-                                       GFP_KERNEL);
+       bdc->srr.sr_bds = dma_alloc_coherent(bdc->dev,
+                                            NUM_SR_ENTRIES * sizeof(struct bdc_bd),
+                                            &bdc->srr.dma_addr, GFP_KERNEL);
        if (!bdc->srr.sr_bds)
                return -ENOMEM;
 
index 660878a..b77f312 100644 (file)
@@ -2083,7 +2083,7 @@ static irqreturn_t net2272_irq(int irq, void *_dev)
 #if defined(PLX_PCI_RDK2)
        /* see if PCI int for us by checking irqstat */
        intcsr = readl(dev->rdk2.fpga_base_addr + RDK2_IRQSTAT);
-       if (!intcsr & (1 << NET2272_PCI_IRQ)) {
+       if (!(intcsr & (1 << NET2272_PCI_IRQ))) {
                spin_unlock(&dev->lock);
                return IRQ_NONE;
        }
index f26109e..66ec1fd 100644 (file)
@@ -302,3 +302,4 @@ MODULE_AUTHOR("Chao Xie <chao.xie@marvell.com>");
 MODULE_AUTHOR("Neil Zhang <zhangwm@marvell.com>");
 MODULE_ALIAS("mv-ehci");
 MODULE_LICENSE("GPL");
+MODULE_DEVICE_TABLE(of, ehci_mv_dt_ids);
index 6218bfe..98deb5f 100644 (file)
@@ -596,9 +596,9 @@ static int uhci_start(struct usb_hcd *hcd)
                                           &uhci_debug_operations);
 #endif
 
-       uhci->frame = dma_zalloc_coherent(uhci_dev(uhci),
-                       UHCI_NUMFRAMES * sizeof(*uhci->frame),
-                       &uhci->frame_dma_handle, GFP_KERNEL);
+       uhci->frame = dma_alloc_coherent(uhci_dev(uhci),
+                                        UHCI_NUMFRAMES * sizeof(*uhci->frame),
+                                        &uhci->frame_dma_handle, GFP_KERNEL);
        if (!uhci->frame) {
                dev_err(uhci_dev(uhci),
                        "unable to allocate consistent memory for frame list\n");
index 36a3eb8..8067f17 100644 (file)
@@ -1672,8 +1672,8 @@ static int scratchpad_alloc(struct xhci_hcd *xhci, gfp_t flags)
        xhci->dcbaa->dev_context_ptrs[0] = cpu_to_le64(xhci->scratchpad->sp_dma);
        for (i = 0; i < num_sp; i++) {
                dma_addr_t dma;
-               void *buf = dma_zalloc_coherent(dev, xhci->page_size, &dma,
-                               flags);
+               void *buf = dma_alloc_coherent(dev, xhci->page_size, &dma,
+                                              flags);
                if (!buf)
                        goto fail_sp4;
 
@@ -1799,8 +1799,8 @@ int xhci_alloc_erst(struct xhci_hcd *xhci,
        struct xhci_erst_entry *entry;
 
        size = sizeof(struct xhci_erst_entry) * evt_ring->num_segs;
-       erst->entries = dma_zalloc_coherent(xhci_to_hcd(xhci)->self.sysdev,
-                                           size, &erst->erst_dma_addr, flags);
+       erst->entries = dma_alloc_coherent(xhci_to_hcd(xhci)->self.sysdev,
+                                          size, &erst->erst_dma_addr, flags);
        if (!erst->entries)
                return -ENOMEM;
 
index eae8b1b..ffe462a 100644 (file)
@@ -452,13 +452,10 @@ void musb_g_tx(struct musb *musb, u8 epnum)
        }
 
        if (request) {
-               u8      is_dma = 0;
-               bool    short_packet = false;
 
                trace_musb_req_tx(req);
 
                if (dma && (csr & MUSB_TXCSR_DMAENAB)) {
-                       is_dma = 1;
                        csr |= MUSB_TXCSR_P_WZC_BITS;
                        csr &= ~(MUSB_TXCSR_DMAENAB | MUSB_TXCSR_P_UNDERRUN |
                                 MUSB_TXCSR_TXPKTRDY | MUSB_TXCSR_AUTOSET);
@@ -476,16 +473,8 @@ void musb_g_tx(struct musb *musb, u8 epnum)
                 */
                if ((request->zero && request->length)
                        && (request->length % musb_ep->packet_sz == 0)
-                       && (request->actual == request->length))
-                               short_packet = true;
+                       && (request->actual == request->length)) {
 
-               if ((musb_dma_inventra(musb) || musb_dma_ux500(musb)) &&
-                       (is_dma && (!dma->desired_mode ||
-                               (request->actual &
-                                       (musb_ep->packet_sz - 1)))))
-                               short_packet = true;
-
-               if (short_packet) {
                        /*
                         * On DMA completion, FIFO may not be
                         * available yet...
index a688f7f..5fc6825 100644 (file)
@@ -346,12 +346,10 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
                                channel->status = MUSB_DMA_STATUS_FREE;
 
                                /* completed */
-                               if ((devctl & MUSB_DEVCTL_HM)
-                                       && (musb_channel->transmit)
-                                       && ((channel->desired_mode == 0)
-                                           || (channel->actual_len &
-                                           (musb_channel->max_packet_sz - 1)))
-                                   ) {
+                               if (musb_channel->transmit &&
+                                       (!channel->desired_mode ||
+                                       (channel->actual_len %
+                                           musb_channel->max_packet_sz))) {
                                        u8  epnum  = musb_channel->epnum;
                                        int offset = musb->io.ep_offset(epnum,
                                                                    MUSB_TXCSR);
@@ -363,11 +361,14 @@ static irqreturn_t dma_controller_irq(int irq, void *private_data)
                                         */
                                        musb_ep_select(mbase, epnum);
                                        txcsr = musb_readw(mbase, offset);
-                                       txcsr &= ~(MUSB_TXCSR_DMAENAB
+                                       if (channel->desired_mode == 1) {
+                                               txcsr &= ~(MUSB_TXCSR_DMAENAB
                                                        | MUSB_TXCSR_AUTOSET);
-                                       musb_writew(mbase, offset, txcsr);
-                                       /* Send out the packet */
-                                       txcsr &= ~MUSB_TXCSR_DMAMODE;
+                                               musb_writew(mbase, offset, txcsr);
+                                               /* Send out the packet */
+                                               txcsr &= ~MUSB_TXCSR_DMAMODE;
+                                               txcsr |= MUSB_TXCSR_DMAENAB;
+                                       }
                                        txcsr |=  MUSB_TXCSR_TXPKTRDY;
                                        musb_writew(mbase, offset, txcsr);
                                }
index d7312ee..91ea308 100644 (file)
@@ -21,7 +21,7 @@ config AB8500_USB
 
 config FSL_USB2_OTG
        bool "Freescale USB OTG Transceiver Driver"
-       depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM && PM
+       depends on USB_EHCI_FSL && USB_FSL_USB2 && USB_OTG_FSM=y && PM
        depends on USB_GADGET || !USB_GADGET # if USB_GADGET=m, this can't be 'y'
        select USB_PHY
        help
index 27bdb72..f5f0568 100644 (file)
@@ -61,9 +61,6 @@ static int am335x_phy_probe(struct platform_device *pdev)
        if (ret)
                return ret;
 
-       ret = usb_add_phy_dev(&am_phy->usb_phy_gen.phy);
-       if (ret)
-               return ret;
        am_phy->usb_phy_gen.phy.init = am335x_init;
        am_phy->usb_phy_gen.phy.shutdown = am335x_shutdown;
 
@@ -82,7 +79,7 @@ static int am335x_phy_probe(struct platform_device *pdev)
        device_set_wakeup_enable(dev, false);
        phy_ctrl_power(am_phy->phy_ctrl, am_phy->id, am_phy->dr_mode, false);
 
-       return 0;
+       return usb_add_phy_dev(&am_phy->usb_phy_gen.phy);
 }
 
 static int am335x_phy_remove(struct platform_device *pdev)
index 1ab2a61..77ef4c4 100644 (file)
@@ -1783,6 +1783,10 @@ static int ftdi_set_bitmode(struct usb_serial_port *port, u8 mode)
        int result;
        u16 val;
 
+       result = usb_autopm_get_interface(serial->interface);
+       if (result)
+               return result;
+
        val = (mode << 8) | (priv->gpio_output << 4) | priv->gpio_value;
        result = usb_control_msg(serial->dev,
                                 usb_sndctrlpipe(serial->dev, 0),
@@ -1795,6 +1799,8 @@ static int ftdi_set_bitmode(struct usb_serial_port *port, u8 mode)
                        val, result);
        }
 
+       usb_autopm_put_interface(serial->interface);
+
        return result;
 }
 
@@ -1846,9 +1852,15 @@ static int ftdi_read_cbus_pins(struct usb_serial_port *port)
        unsigned char *buf;
        int result;
 
+       result = usb_autopm_get_interface(serial->interface);
+       if (result)
+               return result;
+
        buf = kmalloc(1, GFP_KERNEL);
-       if (!buf)
+       if (!buf) {
+               usb_autopm_put_interface(serial->interface);
                return -ENOMEM;
+       }
 
        result = usb_control_msg(serial->dev,
                                 usb_rcvctrlpipe(serial->dev, 0),
@@ -1863,6 +1875,7 @@ static int ftdi_read_cbus_pins(struct usb_serial_port *port)
        }
 
        kfree(buf);
+       usb_autopm_put_interface(serial->interface);
 
        return result;
 }
index 09e21e8..a68f1fb 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
        usa26msg.h
 
index dee454c..a19f3fe 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
        usa28msg.h
 
index 163b2de..8c3970f 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
        usa49msg.h
 
index 20fa3e2..dcf502f 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
        usa67msg.h
 
index 86708ec..c4ca0f6 100644 (file)
@@ -1,3 +1,4 @@
+/* SPDX-License-Identifier: BSD-3-Clause */
 /*
        usa90msg.h
 
index 98e7a5d..bb3f9aa 100644 (file)
@@ -46,6 +46,7 @@ static const struct usb_device_id id_table[] = {
        { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_HCR331) },
        { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_MOTOROLA) },
        { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_ZTEK) },
+       { USB_DEVICE(PL2303_VENDOR_ID, PL2303_PRODUCT_ID_TB) },
        { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID) },
        { USB_DEVICE(IODATA_VENDOR_ID, IODATA_PRODUCT_ID_RSAQ5) },
        { USB_DEVICE(ATEN_VENDOR_ID, ATEN_PRODUCT_ID),
index 4e2554d..559941c 100644 (file)
@@ -8,6 +8,7 @@
 
 #define PL2303_VENDOR_ID       0x067b
 #define PL2303_PRODUCT_ID      0x2303
+#define PL2303_PRODUCT_ID_TB           0x2304
 #define PL2303_PRODUCT_ID_RSAQ2                0x04bb
 #define PL2303_PRODUCT_ID_DCU11                0x1234
 #define PL2303_PRODUCT_ID_PHAROS       0xaaa0
@@ -20,6 +21,7 @@
 #define PL2303_PRODUCT_ID_MOTOROLA     0x0307
 #define PL2303_PRODUCT_ID_ZTEK         0xe1f1
 
+
 #define ATEN_VENDOR_ID         0x0557
 #define ATEN_VENDOR_ID2                0x0547
 #define ATEN_PRODUCT_ID                0x2008
index 4d02735..edbbb13 100644 (file)
@@ -85,7 +85,8 @@ DEVICE(moto_modem, MOTO_IDS);
 /* Motorola Tetra driver */
 #define MOTOROLA_TETRA_IDS()                   \
        { USB_DEVICE(0x0cad, 0x9011) }, /* Motorola Solutions TETRA PEI */ \
-       { USB_DEVICE(0x0cad, 0x9012) }  /* MTP6550 */
+       { USB_DEVICE(0x0cad, 0x9012) }, /* MTP6550 */ \
+       { USB_DEVICE(0x0cad, 0x9016) }  /* TPG2200 */
 DEVICE(motorola_tetra, MOTOROLA_TETRA_IDS);
 
 /* Novatel Wireless GPS driver */
index fde2e71..a73ea49 100644 (file)
@@ -235,8 +235,12 @@ static int slave_configure(struct scsi_device *sdev)
                if (!(us->fflags & US_FL_NEEDS_CAP16))
                        sdev->try_rc_10_first = 1;
 
-               /* assume SPC3 or latter devices support sense size > 18 */
-               if (sdev->scsi_level > SCSI_SPC_2)
+               /*
+                * assume SPC3 or latter devices support sense size > 18
+                * unless US_FL_BAD_SENSE quirk is specified.
+                */
+               if (sdev->scsi_level > SCSI_SPC_2 &&
+                   !(us->fflags & US_FL_BAD_SENSE))
                        us->fflags |= US_FL_SANE_SENSE;
 
                /*
index f7f83b2..ea0d27a 100644 (file)
@@ -1265,6 +1265,18 @@ UNUSUAL_DEV( 0x090c, 0x1132, 0x0000, 0xffff,
                USB_SC_DEVICE, USB_PR_DEVICE, NULL,
                US_FL_FIX_CAPACITY ),
 
+/*
+ * Reported by Icenowy Zheng <icenowy@aosc.io>
+ * The SMI SM3350 USB-UFS bridge controller will enter a wrong state
+ * that do not process read/write command if a long sense is requested,
+ * so force to use 18-byte sense.
+ */
+UNUSUAL_DEV(  0x090c, 0x3350, 0x0000, 0xffff,
+               "SMI",
+               "SM3350 UFS-to-USB-Mass-Storage bridge",
+               USB_SC_DEVICE, USB_PR_DEVICE, NULL,
+               US_FL_BAD_SENSE ),
+
 /*
  * Reported by Paul Hartman <paul.hartman+linux@gmail.com>
  * This card reader returns "Illegal Request, Logical Block Address
index 4bc29b5..f1c39a3 100644 (file)
@@ -2297,7 +2297,8 @@ static unsigned int tcpm_pd_select_pps_apdo(struct tcpm_port *port)
                                              pdo_pps_apdo_max_voltage(snk));
                port->pps_data.max_curr = min_pps_apdo_current(src, snk);
                port->pps_data.out_volt = min(port->pps_data.max_volt,
-                                             port->pps_data.out_volt);
+                                             max(port->pps_data.min_volt,
+                                                 port->pps_data.out_volt));
                port->pps_data.op_curr = min(port->pps_data.max_curr,
                                             port->pps_data.op_curr);
        }
diff --git a/drivers/usb/usbip/README b/drivers/usb/usbip/README
deleted file mode 100644 (file)
index 41a2cf2..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-TODO:
-       - more discussion about the protocol
-       - testing
-       - review of the userspace interface
-       - document the protocol
-
-Please send patches for this code to Greg Kroah-Hartman <greg@kroah.com>
index 228ccdb..b2aa986 100644 (file)
@@ -1,13 +1,9 @@
-/* SPDX-License-Identifier: GPL-2.0+ */
+/* SPDX-License-Identifier: GPL-2.0-only */
 /*
  * VFIO PCI mmap/mmap_fault tracepoints
  *
  * Copyright (C) 2018 IBM Corp.  All rights reserved.
  *     Author: Alexey Kardashevskiy <aik@ozlabs.ru>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
  */
 
 #undef TRACE_SYSTEM
@@ -94,7 +90,7 @@ TRACE_EVENT(vfio_pci_npu2_mmap,
 #endif /* _TRACE_VFIO_PCI_H */
 
 #undef TRACE_INCLUDE_PATH
-#define TRACE_INCLUDE_PATH .
+#define TRACE_INCLUDE_PATH ../../drivers/vfio/pci
 #undef TRACE_INCLUDE_FILE
 #define TRACE_INCLUDE_FILE trace
 
index 054a2cf..32f695f 100644 (file)
@@ -1,14 +1,10 @@
-// SPDX-License-Identifier: GPL-2.0+
+// SPDX-License-Identifier: GPL-2.0-only
 /*
  * VFIO PCI NVIDIA Whitherspoon GPU support a.k.a. NVLink2.
  *
  * Copyright (C) 2018 IBM Corp.  All rights reserved.
  *     Author: Alexey Kardashevskiy <aik@ozlabs.ru>
  *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- *
  * Register an on-GPU RAM region for cacheable access.
  *
  * Derived from original vfio_pci_igd.c:
@@ -178,11 +174,11 @@ static int vfio_pci_nvgpu_add_capability(struct vfio_pci_device *vdev,
                struct vfio_pci_region *region, struct vfio_info_cap *caps)
 {
        struct vfio_pci_nvgpu_data *data = region->data;
-       struct vfio_region_info_cap_nvlink2_ssatgt cap = { 0 };
-
-       cap.header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT;
-       cap.header.version = 1;
-       cap.tgt = data->gpu_tgt;
+       struct vfio_region_info_cap_nvlink2_ssatgt cap = {
+               .header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT,
+               .header.version = 1,
+               .tgt = data->gpu_tgt
+       };
 
        return vfio_info_add_capability(caps, &cap.header, sizeof(cap));
 }
@@ -365,18 +361,18 @@ static int vfio_pci_npu2_add_capability(struct vfio_pci_device *vdev,
                struct vfio_pci_region *region, struct vfio_info_cap *caps)
 {
        struct vfio_pci_npu2_data *data = region->data;
-       struct vfio_region_info_cap_nvlink2_ssatgt captgt = { 0 };
-       struct vfio_region_info_cap_nvlink2_lnkspd capspd = { 0 };
+       struct vfio_region_info_cap_nvlink2_ssatgt captgt = {
+               .header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT,
+               .header.version = 1,
+               .tgt = data->gpu_tgt
+       };
+       struct vfio_region_info_cap_nvlink2_lnkspd capspd = {
+               .header.id = VFIO_REGION_INFO_CAP_NVLINK2_LNKSPD,
+               .header.version = 1,
+               .link_speed = data->link_speed
+       };
        int ret;
 
-       captgt.header.id = VFIO_REGION_INFO_CAP_NVLINK2_SSATGT;
-       captgt.header.version = 1;
-       captgt.tgt = data->gpu_tgt;
-
-       capspd.header.id = VFIO_REGION_INFO_CAP_NVLINK2_LNKSPD;
-       capspd.header.version = 1;
-       capspd.link_speed = data->link_speed;
-
        ret = vfio_info_add_capability(caps, &captgt.header, sizeof(captgt));
        if (ret)
                return ret;
index 7651cfb..73652e2 100644 (file)
@@ -878,7 +878,7 @@ static int vfio_dma_do_unmap(struct vfio_iommu *iommu,
                return -EINVAL;
        if (!unmap->size || unmap->size & mask)
                return -EINVAL;
-       if (unmap->iova + unmap->size < unmap->iova ||
+       if (unmap->iova + unmap->size - 1 < unmap->iova ||
            unmap->size > SIZE_MAX)
                return -EINVAL;
 
index 36f3d0f..df51a35 100644 (file)
@@ -1236,7 +1236,8 @@ static void handle_rx(struct vhost_net *net)
                if (nvq->done_idx > VHOST_NET_BATCH)
                        vhost_net_signal_used(nvq);
                if (unlikely(vq_log))
-                       vhost_log_write(vq, vq_log, log, vhost_len);
+                       vhost_log_write(vq, vq_log, log, vhost_len,
+                                       vq->iov, in);
                total_len += vhost_len;
                if (unlikely(vhost_exceeds_weight(++recv_pkts, total_len))) {
                        vhost_poll_queue(&vq->poll);
@@ -1336,7 +1337,8 @@ static int vhost_net_open(struct inode *inode, struct file *f)
                n->vqs[i].rx_ring = NULL;
                vhost_net_buf_init(&n->vqs[i].rxq);
        }
-       vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX);
+       vhost_dev_init(dev, vqs, VHOST_NET_VQ_MAX,
+                      UIO_MAXIOV + VHOST_NET_BATCH);
 
        vhost_poll_init(n->poll + VHOST_NET_VQ_TX, handle_tx_net, EPOLLOUT, dev);
        vhost_poll_init(n->poll + VHOST_NET_VQ_RX, handle_rx_net, EPOLLIN, dev);
index 8e10ab4..23593cb 100644 (file)
@@ -1127,16 +1127,18 @@ vhost_scsi_send_tmf_reject(struct vhost_scsi *vs,
                           struct vhost_virtqueue *vq,
                           struct vhost_scsi_ctx *vc)
 {
-       struct virtio_scsi_ctrl_tmf_resp __user *resp;
        struct virtio_scsi_ctrl_tmf_resp rsp;
+       struct iov_iter iov_iter;
        int ret;
 
        pr_debug("%s\n", __func__);
        memset(&rsp, 0, sizeof(rsp));
        rsp.response = VIRTIO_SCSI_S_FUNCTION_REJECTED;
-       resp = vq->iov[vc->out].iov_base;
-       ret = __copy_to_user(resp, &rsp, sizeof(rsp));
-       if (!ret)
+
+       iov_iter_init(&iov_iter, READ, &vq->iov[vc->out], vc->in, sizeof(rsp));
+
+       ret = copy_to_iter(&rsp, sizeof(rsp), &iov_iter);
+       if (likely(ret == sizeof(rsp)))
                vhost_add_used_and_signal(&vs->dev, vq, vc->head, 0);
        else
                pr_err("Faulted on virtio_scsi_ctrl_tmf_resp\n");
@@ -1147,16 +1149,18 @@ vhost_scsi_send_an_resp(struct vhost_scsi *vs,
                        struct vhost_virtqueue *vq,
                        struct vhost_scsi_ctx *vc)
 {
-       struct virtio_scsi_ctrl_an_resp __user *resp;
        struct virtio_scsi_ctrl_an_resp rsp;
+       struct iov_iter iov_iter;
        int ret;
 
        pr_debug("%s\n", __func__);
        memset(&rsp, 0, sizeof(rsp));   /* event_actual = 0 */
        rsp.response = VIRTIO_SCSI_S_OK;
-       resp = vq->iov[vc->out].iov_base;
-       ret = __copy_to_user(resp, &rsp, sizeof(rsp));
-       if (!ret)
+
+       iov_iter_init(&iov_iter, READ, &vq->iov[vc->out], vc->in, sizeof(rsp));
+
+       ret = copy_to_iter(&rsp, sizeof(rsp), &iov_iter);
+       if (likely(ret == sizeof(rsp)))
                vhost_add_used_and_signal(&vs->dev, vq, vc->head, 0);
        else
                pr_err("Faulted on virtio_scsi_ctrl_an_resp\n");
@@ -1623,7 +1627,7 @@ static int vhost_scsi_open(struct inode *inode, struct file *f)
                vqs[i] = &vs->vqs[i].vq;
                vs->vqs[i].vq.handle_kick = vhost_scsi_handle_kick;
        }
-       vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ);
+       vhost_dev_init(&vs->dev, vqs, VHOST_SCSI_MAX_VQ, UIO_MAXIOV);
 
        vhost_scsi_init_inflight(vs, NULL);
 
index 9f7942c..a2e5dc7 100644 (file)
@@ -390,9 +390,9 @@ static long vhost_dev_alloc_iovecs(struct vhost_dev *dev)
                vq->indirect = kmalloc_array(UIO_MAXIOV,
                                             sizeof(*vq->indirect),
                                             GFP_KERNEL);
-               vq->log = kmalloc_array(UIO_MAXIOV, sizeof(*vq->log),
+               vq->log = kmalloc_array(dev->iov_limit, sizeof(*vq->log),
                                        GFP_KERNEL);
-               vq->heads = kmalloc_array(UIO_MAXIOV, sizeof(*vq->heads),
+               vq->heads = kmalloc_array(dev->iov_limit, sizeof(*vq->heads),
                                          GFP_KERNEL);
                if (!vq->indirect || !vq->log || !vq->heads)
                        goto err_nomem;
@@ -414,7 +414,7 @@ static void vhost_dev_free_iovecs(struct vhost_dev *dev)
 }
 
 void vhost_dev_init(struct vhost_dev *dev,
-                   struct vhost_virtqueue **vqs, int nvqs)
+                   struct vhost_virtqueue **vqs, int nvqs, int iov_limit)
 {
        struct vhost_virtqueue *vq;
        int i;
@@ -427,6 +427,7 @@ void vhost_dev_init(struct vhost_dev *dev,
        dev->iotlb = NULL;
        dev->mm = NULL;
        dev->worker = NULL;
+       dev->iov_limit = iov_limit;
        init_llist_head(&dev->work_list);
        init_waitqueue_head(&dev->wait);
        INIT_LIST_HEAD(&dev->read_list);
@@ -1034,8 +1035,10 @@ ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
        int type, ret;
 
        ret = copy_from_iter(&type, sizeof(type), from);
-       if (ret != sizeof(type))
+       if (ret != sizeof(type)) {
+               ret = -EINVAL;
                goto done;
+       }
 
        switch (type) {
        case VHOST_IOTLB_MSG:
@@ -1054,8 +1057,10 @@ ssize_t vhost_chr_write_iter(struct vhost_dev *dev,
 
        iov_iter_advance(from, offset);
        ret = copy_from_iter(&msg, sizeof(msg), from);
-       if (ret != sizeof(msg))
+       if (ret != sizeof(msg)) {
+               ret = -EINVAL;
                goto done;
+       }
        if (vhost_process_iotlb_msg(dev, &msg)) {
                ret = -EFAULT;
                goto done;
@@ -1733,13 +1738,87 @@ static int log_write(void __user *log_base,
        return r;
 }
 
+static int log_write_hva(struct vhost_virtqueue *vq, u64 hva, u64 len)
+{
+       struct vhost_umem *umem = vq->umem;
+       struct vhost_umem_node *u;
+       u64 start, end, l, min;
+       int r;
+       bool hit = false;
+
+       while (len) {
+               min = len;
+               /* More than one GPAs can be mapped into a single HVA. So
+                * iterate all possible umems here to be safe.
+                */
+               list_for_each_entry(u, &umem->umem_list, link) {
+                       if (u->userspace_addr > hva - 1 + len ||
+                           u->userspace_addr - 1 + u->size < hva)
+                               continue;
+                       start = max(u->userspace_addr, hva);
+                       end = min(u->userspace_addr - 1 + u->size,
+                                 hva - 1 + len);
+                       l = end - start + 1;
+                       r = log_write(vq->log_base,
+                                     u->start + start - u->userspace_addr,
+                                     l);
+                       if (r < 0)
+                               return r;
+                       hit = true;
+                       min = min(l, min);
+               }
+
+               if (!hit)
+                       return -EFAULT;
+
+               len -= min;
+               hva += min;
+       }
+
+       return 0;
+}
+
+static int log_used(struct vhost_virtqueue *vq, u64 used_offset, u64 len)
+{
+       struct iovec iov[64];
+       int i, ret;
+
+       if (!vq->iotlb)
+               return log_write(vq->log_base, vq->log_addr + used_offset, len);
+
+       ret = translate_desc(vq, (uintptr_t)vq->used + used_offset,
+                            len, iov, 64, VHOST_ACCESS_WO);
+       if (ret < 0)
+               return ret;
+
+       for (i = 0; i < ret; i++) {
+               ret = log_write_hva(vq, (uintptr_t)iov[i].iov_base,
+                                   iov[i].iov_len);
+               if (ret)
+                       return ret;
+       }
+
+       return 0;
+}
+
 int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
-                   unsigned int log_num, u64 len)
+                   unsigned int log_num, u64 len, struct iovec *iov, int count)
 {
        int i, r;
 
        /* Make sure data written is seen before log. */
        smp_wmb();
+
+       if (vq->iotlb) {
+               for (i = 0; i < count; i++) {
+                       r = log_write_hva(vq, (uintptr_t)iov[i].iov_base,
+                                         iov[i].iov_len);
+                       if (r < 0)
+                               return r;
+               }
+               return 0;
+       }
+
        for (i = 0; i < log_num; ++i) {
                u64 l = min(log[i].len, len);
                r = log_write(vq->log_base, log[i].addr, l);
@@ -1769,9 +1848,8 @@ static int vhost_update_used_flags(struct vhost_virtqueue *vq)
                smp_wmb();
                /* Log used flag write. */
                used = &vq->used->flags;
-               log_write(vq->log_base, vq->log_addr +
-                         (used - (void __user *)vq->used),
-                         sizeof vq->used->flags);
+               log_used(vq, (used - (void __user *)vq->used),
+                        sizeof vq->used->flags);
                if (vq->log_ctx)
                        eventfd_signal(vq->log_ctx, 1);
        }
@@ -1789,9 +1867,8 @@ static int vhost_update_avail_event(struct vhost_virtqueue *vq, u16 avail_event)
                smp_wmb();
                /* Log avail event write */
                used = vhost_avail_event(vq);
-               log_write(vq->log_base, vq->log_addr +
-                         (used - (void __user *)vq->used),
-                         sizeof *vhost_avail_event(vq));
+               log_used(vq, (used - (void __user *)vq->used),
+                        sizeof *vhost_avail_event(vq));
                if (vq->log_ctx)
                        eventfd_signal(vq->log_ctx, 1);
        }
@@ -2191,10 +2268,8 @@ static int __vhost_add_used_n(struct vhost_virtqueue *vq,
                /* Make sure data is seen before log. */
                smp_wmb();
                /* Log used ring entry write. */
-               log_write(vq->log_base,
-                         vq->log_addr +
-                          ((void __user *)used - (void __user *)vq->used),
-                         count * sizeof *used);
+               log_used(vq, ((void __user *)used - (void __user *)vq->used),
+                        count * sizeof *used);
        }
        old = vq->last_used_idx;
        new = (vq->last_used_idx += count);
@@ -2236,9 +2311,8 @@ int vhost_add_used_n(struct vhost_virtqueue *vq, struct vring_used_elem *heads,
                /* Make sure used idx is seen before log. */
                smp_wmb();
                /* Log used index update. */
-               log_write(vq->log_base,
-                         vq->log_addr + offsetof(struct vring_used, idx),
-                         sizeof vq->used->idx);
+               log_used(vq, offsetof(struct vring_used, idx),
+                        sizeof vq->used->idx);
                if (vq->log_ctx)
                        eventfd_signal(vq->log_ctx, 1);
        }
index 466ef75..9490e7d 100644 (file)
@@ -170,9 +170,11 @@ struct vhost_dev {
        struct list_head read_list;
        struct list_head pending_list;
        wait_queue_head_t wait;
+       int iov_limit;
 };
 
-void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs, int nvqs);
+void vhost_dev_init(struct vhost_dev *, struct vhost_virtqueue **vqs,
+                   int nvqs, int iov_limit);
 long vhost_dev_set_owner(struct vhost_dev *dev);
 bool vhost_dev_has_owner(struct vhost_dev *dev);
 long vhost_dev_check_owner(struct vhost_dev *);
@@ -205,7 +207,8 @@ bool vhost_vq_avail_empty(struct vhost_dev *, struct vhost_virtqueue *);
 bool vhost_enable_notify(struct vhost_dev *, struct vhost_virtqueue *);
 
 int vhost_log_write(struct vhost_virtqueue *vq, struct vhost_log *log,
-                   unsigned int log_num, u64 len);
+                   unsigned int log_num, u64 len,
+                   struct iovec *iov, int count);
 int vq_iotlb_prefetch(struct vhost_virtqueue *vq);
 
 struct vhost_msg_node *vhost_new_msg(struct vhost_virtqueue *vq, int type);
index bc42d38..bb5fc0e 100644 (file)
@@ -531,7 +531,7 @@ static int vhost_vsock_dev_open(struct inode *inode, struct file *file)
        vsock->vqs[VSOCK_VQ_TX].handle_kick = vhost_vsock_handle_tx_kick;
        vsock->vqs[VSOCK_VQ_RX].handle_kick = vhost_vsock_handle_rx_kick;
 
-       vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs));
+       vhost_dev_init(&vsock->dev, vqs, ARRAY_SIZE(vsock->vqs), UIO_MAXIOV);
 
        file->private_data = vsock;
        spin_lock_init(&vsock->send_pkt_list_lock);
@@ -642,7 +642,7 @@ static int vhost_vsock_set_cid(struct vhost_vsock *vsock, u64 guest_cid)
                hash_del_rcu(&vsock->hash);
 
        vsock->guest_cid = guest_cid;
-       hash_add_rcu(vhost_vsock_hash, &vsock->hash, guest_cid);
+       hash_add_rcu(vhost_vsock_hash, &vsock->hash, vsock->guest_cid);
        mutex_unlock(&vhost_vsock_mutex);
 
        return 0;
index 6d8dc2c..51e0c4b 100644 (file)
@@ -174,7 +174,7 @@ static int pm860x_backlight_dt_init(struct platform_device *pdev,
                return -ENODEV;
        }
        for_each_child_of_node(nproot, np) {
-               if (!of_node_cmp(np->name, name)) {
+               if (of_node_name_eq(np, name)) {
                        of_property_read_u32(np, "marvell,88pm860x-iset",
                                             &iset);
                        data->iset = PM8606_WLED_CURRENT(iset);
index f9ef067..feb9076 100644 (file)
@@ -30,6 +30,7 @@ struct pwm_bl_data {
        struct device           *dev;
        unsigned int            lth_brightness;
        unsigned int            *levels;
+       bool                    enabled;
        struct regulator        *power_supply;
        struct gpio_desc        *enable_gpio;
        unsigned int            scale;
@@ -50,7 +51,7 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb)
        int err;
 
        pwm_get_state(pb->pwm, &state);
-       if (state.enabled)
+       if (pb->enabled)
                return;
 
        err = regulator_enable(pb->power_supply);
@@ -65,6 +66,8 @@ static void pwm_backlight_power_on(struct pwm_bl_data *pb)
 
        if (pb->enable_gpio)
                gpiod_set_value_cansleep(pb->enable_gpio, 1);
+
+       pb->enabled = true;
 }
 
 static void pwm_backlight_power_off(struct pwm_bl_data *pb)
@@ -72,7 +75,7 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb)
        struct pwm_state state;
 
        pwm_get_state(pb->pwm, &state);
-       if (!state.enabled)
+       if (!pb->enabled)
                return;
 
        if (pb->enable_gpio)
@@ -86,6 +89,7 @@ static void pwm_backlight_power_off(struct pwm_bl_data *pb)
        pwm_apply_state(pb->pwm, &state);
 
        regulator_disable(pb->power_supply);
+       pb->enabled = false;
 }
 
 static int compute_duty_cycle(struct pwm_bl_data *pb, int brightness)
@@ -268,6 +272,16 @@ static int pwm_backlight_parse_dt(struct device *dev,
 
        memset(data, 0, sizeof(*data));
 
+       /*
+        * These values are optional and set as 0 by default, the out values
+        * are modified only if a valid u32 value can be decoded.
+        */
+       of_property_read_u32(node, "post-pwm-on-delay-ms",
+                            &data->post_pwm_on_delay);
+       of_property_read_u32(node, "pwm-off-delay-ms", &data->pwm_off_delay);
+
+       data->enable_gpio = -EINVAL;
+
        /*
         * Determine the number of brightness levels, if this property is not
         * set a default table of brightness levels will be used.
@@ -380,15 +394,6 @@ static int pwm_backlight_parse_dt(struct device *dev,
                data->max_brightness--;
        }
 
-       /*
-        * These values are optional and set as 0 by default, the out values
-        * are modified only if a valid u32 value can be decoded.
-        */
-       of_property_read_u32(node, "post-pwm-on-delay-ms",
-                            &data->post_pwm_on_delay);
-       of_property_read_u32(node, "pwm-off-delay-ms", &data->pwm_off_delay);
-
-       data->enable_gpio = -EINVAL;
        return 0;
 }
 
@@ -483,6 +488,7 @@ static int pwm_backlight_probe(struct platform_device *pdev)
        pb->check_fb = data->check_fb;
        pb->exit = data->exit;
        pb->dev = &pdev->dev;
+       pb->enabled = false;
        pb->post_pwm_on_delay = data->post_pwm_on_delay;
        pb->pwm_off_delay = data->pwm_off_delay;
 
index 09731b2..c6b3bdb 100644 (file)
@@ -271,6 +271,7 @@ static void vgacon_scrollback_update(struct vc_data *c, int t, int count)
 
 static void vgacon_restore_screen(struct vc_data *c)
 {
+       c->vc_origin = c->vc_visible_origin;
        vgacon_scrollback_cur->save = 0;
 
        if (!vga_is_gfx && !vgacon_scrollback_cur->restore) {
@@ -287,8 +288,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
        int start, end, count, soff;
 
        if (!lines) {
-               c->vc_visible_origin = c->vc_origin;
-               vga_set_mem_top(c);
+               vgacon_restore_screen(c);
                return;
        }
 
@@ -298,6 +298,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
        if (!vgacon_scrollback_cur->save) {
                vgacon_cursor(c, CM_ERASE);
                vgacon_save_screen(c);
+               c->vc_origin = (unsigned long)c->vc_screenbuf;
                vgacon_scrollback_cur->save = 1;
        }
 
@@ -335,7 +336,7 @@ static void vgacon_scrolldelta(struct vc_data *c, int lines)
                int copysize;
 
                int diff = c->vc_rows - count;
-               void *d = (void *) c->vc_origin;
+               void *d = (void *) c->vc_visible_origin;
                void *s = (void *) c->vc_screenbuf;
 
                count *= c->vc_size_row;
index 8976190..bfa1360 100644 (file)
@@ -510,6 +510,13 @@ static int __init fb_console_setup(char *this_opt)
                        continue;
                }
 #endif
+
+               if (!strncmp(options, "logo-pos:", 9)) {
+                       options += 9;
+                       if (!strcmp(options, "center"))
+                               fb_center_logo = true;
+                       continue;
+               }
        }
        return 1;
 }
index 558ed2e..cb43a22 100644 (file)
@@ -53,6 +53,9 @@ EXPORT_SYMBOL(registered_fb);
 int num_registered_fb __read_mostly;
 EXPORT_SYMBOL(num_registered_fb);
 
+bool fb_center_logo __read_mostly;
+EXPORT_SYMBOL(fb_center_logo);
+
 static struct fb_info *get_fb_info(unsigned int idx)
 {
        struct fb_info *fb_info;
@@ -506,8 +509,7 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
                fb_set_logo(info, logo, logo_new, fb_logo.depth);
        }
 
-#ifdef CONFIG_FB_LOGO_CENTER
-       {
+       if (fb_center_logo) {
                int xres = info->var.xres;
                int yres = info->var.yres;
 
@@ -520,11 +522,11 @@ static int fb_show_logo_line(struct fb_info *info, int rotate,
                        --n;
                image.dx = (xres - n * (logo->width + 8) - 8) / 2;
                image.dy = y ?: (yres - logo->height) / 2;
+       } else {
+               image.dx = 0;
+               image.dy = y;
        }
-#else
-       image.dx = 0;
-       image.dy = y;
-#endif
+
        image.width = logo->width;
        image.height = logo->height;
 
@@ -684,9 +686,8 @@ int fb_prepare_logo(struct fb_info *info, int rotate)
        }
 
        height = fb_logo.logo->height;
-#ifdef CONFIG_FB_LOGO_CENTER
-       height += (yres - fb_logo.logo->height) / 2;
-#endif
+       if (fb_center_logo)
+               height += (yres - fb_logo.logo->height) / 2;
 
        return fb_prepare_extra_logos(info, height, yres);
 }
index a74096c..43f2a48 100644 (file)
@@ -1446,9 +1446,9 @@ static int fb_probe(struct platform_device *device)
                da8xx_fb_fix.line_length - 1;
 
        /* allocate palette buffer */
-       par->v_palette_base = dma_zalloc_coherent(NULL, PALETTE_SIZE,
-                                                 &par->p_palette_base,
-                                                 GFP_KERNEL | GFP_DMA);
+       par->v_palette_base = dma_alloc_coherent(NULL, PALETTE_SIZE,
+                                                &par->p_palette_base,
+                                                GFP_KERNEL | GFP_DMA);
        if (!par->v_palette_base) {
                dev_err(&device->dev,
                        "GLCD: kmalloc for palette buffer failed\n");
index 31f769d..057d3cd 100644 (file)
@@ -318,28 +318,28 @@ static void __iomem *offb_map_reg(struct device_node *np, int index,
 }
 
 static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp,
-                                   const char *name, unsigned long address)
+                                   unsigned long address)
 {
        struct offb_par *par = (struct offb_par *) info->par;
 
-       if (dp && !strncmp(name, "ATY,Rage128", 11)) {
+       if (of_node_name_prefix(dp, "ATY,Rage128")) {
                par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
                if (par->cmap_adr)
                        par->cmap_type = cmap_r128;
-       } else if (dp && (!strncmp(name, "ATY,RageM3pA", 12)
-                         || !strncmp(name, "ATY,RageM3p12A", 14))) {
+       } else if (of_node_name_prefix(dp, "ATY,RageM3pA") ||
+                  of_node_name_prefix(dp, "ATY,RageM3p12A")) {
                par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
                if (par->cmap_adr)
                        par->cmap_type = cmap_M3A;
-       } else if (dp && !strncmp(name, "ATY,RageM3pB", 12)) {
+       } else if (of_node_name_prefix(dp, "ATY,RageM3pB")) {
                par->cmap_adr = offb_map_reg(dp, 2, 0, 0x1fff);
                if (par->cmap_adr)
                        par->cmap_type = cmap_M3B;
-       } else if (dp && !strncmp(name, "ATY,Rage6", 9)) {
+       } else if (of_node_name_prefix(dp, "ATY,Rage6")) {
                par->cmap_adr = offb_map_reg(dp, 1, 0, 0x1fff);
                if (par->cmap_adr)
                        par->cmap_type = cmap_radeon;
-       } else if (!strncmp(name, "ATY,", 4)) {
+       } else if (of_node_name_prefix(dp, "ATY,")) {
                unsigned long base = address & 0xff000000UL;
                par->cmap_adr =
                        ioremap(base + 0x7ff000, 0x1000) + 0xcc0;
@@ -350,7 +350,7 @@ static void offb_init_palette_hacks(struct fb_info *info, struct device_node *dp
                par->cmap_adr = offb_map_reg(dp, 0, 0x6000, 0x1000);
                if (par->cmap_adr)
                        par->cmap_type = cmap_gxt2000;
-       } else if (dp && !strncmp(name, "vga,Display-", 12)) {
+       } else if (of_node_name_prefix(dp, "vga,Display-")) {
                /* Look for AVIVO initialized by SLOF */
                struct device_node *pciparent = of_get_parent(dp);
                const u32 *vid, *did;
@@ -438,7 +438,7 @@ static void __init offb_init_fb(const char *name,
 
        par->cmap_type = cmap_unknown;
        if (depth == 8)
-               offb_init_palette_hacks(info, dp, name, address);
+               offb_init_palette_hacks(info, dp, address);
        else
                fix->visual = FB_VISUAL_TRUECOLOR;
 
index 53f9361..8e23160 100644 (file)
@@ -609,6 +609,8 @@ int omapfb_ioctl(struct fb_info *fbi, unsigned int cmd, unsigned long arg)
 
        int r = 0;
 
+       memset(&p, 0, sizeof(p));
+
        switch (cmd) {
        case OMAPFB_SYNC_GFX:
                DBG("ioctl SYNC_GFX\n");
index 1e972c4..d1f6196 100644 (file)
@@ -10,15 +10,6 @@ menuconfig LOGO
 
 if LOGO
 
-config FB_LOGO_CENTER
-       bool "Center the logo"
-       depends on FB=y
-       help
-         When this option is selected, the bootup logo is centered both
-         horizontally and vertically. If more than one logo is displayed
-         due to multiple CPUs, the collected line of logos is centered
-         as a whole.
-
 config FB_LOGO_EXTRA
        bool
        depends on FB=y
index 728ecd1..fb12fe2 100644 (file)
@@ -61,6 +61,10 @@ enum virtio_balloon_vq {
        VIRTIO_BALLOON_VQ_MAX
 };
 
+enum virtio_balloon_config_read {
+       VIRTIO_BALLOON_CONFIG_READ_CMD_ID = 0,
+};
+
 struct virtio_balloon {
        struct virtio_device *vdev;
        struct virtqueue *inflate_vq, *deflate_vq, *stats_vq, *free_page_vq;
@@ -77,14 +81,20 @@ struct virtio_balloon {
        /* Prevent updating balloon when it is being canceled. */
        spinlock_t stop_update_lock;
        bool stop_update;
+       /* Bitmap to indicate if reading the related config fields are needed */
+       unsigned long config_read_bitmap;
 
        /* The list of allocated free pages, waiting to be given back to mm */
        struct list_head free_page_list;
        spinlock_t free_page_list_lock;
        /* The number of free page blocks on the above list */
        unsigned long num_free_page_blocks;
-       /* The cmd id received from host */
-       u32 cmd_id_received;
+       /*
+        * The cmd id received from host.
+        * Read it via virtio_balloon_cmd_id_received to get the latest value
+        * sent from host.
+        */
+       u32 cmd_id_received_cache;
        /* The cmd id that is actively in use */
        __virtio32 cmd_id_active;
        /* Buffer to store the stop sign */
@@ -390,37 +400,31 @@ static unsigned long return_free_pages_to_mm(struct virtio_balloon *vb,
        return num_returned;
 }
 
+static void virtio_balloon_queue_free_page_work(struct virtio_balloon *vb)
+{
+       if (!virtio_has_feature(vb->vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT))
+               return;
+
+       /* No need to queue the work if the bit was already set. */
+       if (test_and_set_bit(VIRTIO_BALLOON_CONFIG_READ_CMD_ID,
+                            &vb->config_read_bitmap))
+               return;
+
+       queue_work(vb->balloon_wq, &vb->report_free_page_work);
+}
+
 static void virtballoon_changed(struct virtio_device *vdev)
 {
        struct virtio_balloon *vb = vdev->priv;
        unsigned long flags;
-       s64 diff = towards_target(vb);
-
-       if (diff) {
-               spin_lock_irqsave(&vb->stop_update_lock, flags);
-               if (!vb->stop_update)
-                       queue_work(system_freezable_wq,
-                                  &vb->update_balloon_size_work);
-               spin_unlock_irqrestore(&vb->stop_update_lock, flags);
-       }
 
-       if (virtio_has_feature(vdev, VIRTIO_BALLOON_F_FREE_PAGE_HINT)) {
-               virtio_cread(vdev, struct virtio_balloon_config,
-                            free_page_report_cmd_id, &vb->cmd_id_received);
-               if (vb->cmd_id_received == VIRTIO_BALLOON_CMD_ID_DONE) {
-                       /* Pass ULONG_MAX to give back all the free pages */
-                       return_free_pages_to_mm(vb, ULONG_MAX);
-               } else if (vb->cmd_id_received != VIRTIO_BALLOON_CMD_ID_STOP &&
-                          vb->cmd_id_received !=
-                          virtio32_to_cpu(vdev, vb->cmd_id_active)) {
-                       spin_lock_irqsave(&vb->stop_update_lock, flags);
-                       if (!vb->stop_update) {
-                               queue_work(vb->balloon_wq,
-                                          &vb->report_free_page_work);
-                       }
-                       spin_unlock_irqrestore(&vb->stop_update_lock, flags);
-               }
+       spin_lock_irqsave(&vb->stop_update_lock, flags);
+       if (!vb->stop_update) {
+               queue_work(system_freezable_wq,
+                          &vb->update_balloon_size_work);
+               virtio_balloon_queue_free_page_work(vb);
        }
+       spin_unlock_irqrestore(&vb->stop_update_lock, flags);
 }
 
 static void update_balloon_size(struct virtio_balloon *vb)
@@ -527,6 +531,17 @@ static int init_vqs(struct virtio_balloon *vb)
        return 0;
 }
 
+static u32 virtio_balloon_cmd_id_received(struct virtio_balloon *vb)
+{
+       if (test_and_clear_bit(VIRTIO_BALLOON_CONFIG_READ_CMD_ID,
+                              &vb->config_read_bitmap))
+               virtio_cread(vb->vdev, struct virtio_balloon_config,
+                            free_page_report_cmd_id,
+                            &vb->cmd_id_received_cache);
+
+       return vb->cmd_id_received_cache;
+}
+
 static int send_cmd_id_start(struct virtio_balloon *vb)
 {
        struct scatterlist sg;
@@ -537,7 +552,8 @@ static int send_cmd_id_start(struct virtio_balloon *vb)
        while (virtqueue_get_buf(vq, &unused))
                ;
 
-       vb->cmd_id_active = cpu_to_virtio32(vb->vdev, vb->cmd_id_received);
+       vb->cmd_id_active = virtio32_to_cpu(vb->vdev,
+                                       virtio_balloon_cmd_id_received(vb));
        sg_init_one(&sg, &vb->cmd_id_active, sizeof(vb->cmd_id_active));
        err = virtqueue_add_outbuf(vq, &sg, 1, &vb->cmd_id_active, GFP_KERNEL);
        if (!err)
@@ -620,7 +636,8 @@ static int send_free_pages(struct virtio_balloon *vb)
                 * stop the reporting.
                 */
                cmd_id_active = virtio32_to_cpu(vb->vdev, vb->cmd_id_active);
-               if (cmd_id_active != vb->cmd_id_received)
+               if (unlikely(cmd_id_active !=
+                            virtio_balloon_cmd_id_received(vb)))
                        break;
 
                /*
@@ -637,11 +654,9 @@ static int send_free_pages(struct virtio_balloon *vb)
        return 0;
 }
 
-static void report_free_page_func(struct work_struct *work)
+static void virtio_balloon_report_free_page(struct virtio_balloon *vb)
 {
        int err;
-       struct virtio_balloon *vb = container_of(work, struct virtio_balloon,
-                                                report_free_page_work);
        struct device *dev = &vb->vdev->dev;
 
        /* Start by sending the received cmd id to host with an outbuf. */
@@ -659,6 +674,23 @@ static void report_free_page_func(struct work_struct *work)
                dev_err(dev, "Failed to send a stop id, err = %d\n", err);
 }
 
+static void report_free_page_func(struct work_struct *work)
+{
+       struct virtio_balloon *vb = container_of(work, struct virtio_balloon,
+                                                report_free_page_work);
+       u32 cmd_id_received;
+
+       cmd_id_received = virtio_balloon_cmd_id_received(vb);
+       if (cmd_id_received == VIRTIO_BALLOON_CMD_ID_DONE) {
+               /* Pass ULONG_MAX to give back all the free pages */
+               return_free_pages_to_mm(vb, ULONG_MAX);
+       } else if (cmd_id_received != VIRTIO_BALLOON_CMD_ID_STOP &&
+                  cmd_id_received !=
+                  virtio32_to_cpu(vb->vdev, vb->cmd_id_active)) {
+               virtio_balloon_report_free_page(vb);
+       }
+}
+
 #ifdef CONFIG_BALLOON_COMPACTION
 /*
  * virtballoon_migratepage - perform the balloon page migration on behalf of
@@ -885,7 +917,7 @@ static int virtballoon_probe(struct virtio_device *vdev)
                        goto out_del_vqs;
                }
                INIT_WORK(&vb->report_free_page_work, report_free_page_func);
-               vb->cmd_id_received = VIRTIO_BALLOON_CMD_ID_STOP;
+               vb->cmd_id_received_cache = VIRTIO_BALLOON_CMD_ID_STOP;
                vb->cmd_id_active = cpu_to_virtio32(vb->vdev,
                                                  VIRTIO_BALLOON_CMD_ID_STOP);
                vb->cmd_id_stop = cpu_to_virtio32(vb->vdev,
index 4cd9ea5..d9dd0f7 100644 (file)
@@ -468,7 +468,7 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
 {
        struct virtio_mmio_device *vm_dev = to_virtio_mmio_device(vdev);
        unsigned int irq = platform_get_irq(vm_dev->pdev, 0);
-       int i, err;
+       int i, err, queue_idx = 0;
 
        err = request_irq(irq, vm_interrupt, IRQF_SHARED,
                        dev_name(&vdev->dev), vm_dev);
@@ -476,7 +476,12 @@ static int vm_find_vqs(struct virtio_device *vdev, unsigned nvqs,
                return err;
 
        for (i = 0; i < nvqs; ++i) {
-               vqs[i] = vm_setup_vq(vdev, i, callbacks[i], names[i],
+               if (!names[i]) {
+                       vqs[i] = NULL;
+                       continue;
+               }
+
+               vqs[i] = vm_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
                                     ctx ? ctx[i] : false);
                if (IS_ERR(vqs[i])) {
                        vm_del_vqs(vdev);
index 465a6f5..d0584c0 100644 (file)
@@ -285,7 +285,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
        u16 msix_vec;
-       int i, err, nvectors, allocated_vectors;
+       int i, err, nvectors, allocated_vectors, queue_idx = 0;
 
        vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
        if (!vp_dev->vqs)
@@ -321,7 +321,7 @@ static int vp_find_vqs_msix(struct virtio_device *vdev, unsigned nvqs,
                        msix_vec = allocated_vectors++;
                else
                        msix_vec = VP_MSIX_VQ_VECTOR;
-               vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i],
+               vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
                                     ctx ? ctx[i] : false,
                                     msix_vec);
                if (IS_ERR(vqs[i])) {
@@ -356,7 +356,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
                const char * const names[], const bool *ctx)
 {
        struct virtio_pci_device *vp_dev = to_vp_device(vdev);
-       int i, err;
+       int i, err, queue_idx = 0;
 
        vp_dev->vqs = kcalloc(nvqs, sizeof(*vp_dev->vqs), GFP_KERNEL);
        if (!vp_dev->vqs)
@@ -374,7 +374,7 @@ static int vp_find_vqs_intx(struct virtio_device *vdev, unsigned nvqs,
                        vqs[i] = NULL;
                        continue;
                }
-               vqs[i] = vp_setup_vq(vdev, i, callbacks[i], names[i],
+               vqs[i] = vp_setup_vq(vdev, queue_idx++, callbacks[i], names[i],
                                     ctx ? ctx[i] : false,
                                     VIRTIO_MSI_NO_VECTOR);
                if (IS_ERR(vqs[i])) {
index cd7e755..a0b07c3 100644 (file)
@@ -152,7 +152,12 @@ struct vring_virtqueue {
                /* Available for packed ring */
                struct {
                        /* Actual memory layout for this queue. */
-                       struct vring_packed vring;
+                       struct {
+                               unsigned int num;
+                               struct vring_packed_desc *desc;
+                               struct vring_packed_desc_event *driver;
+                               struct vring_packed_desc_event *device;
+                       } vring;
 
                        /* Driver ring wrap counter. */
                        bool avail_wrap_counter;
@@ -1609,6 +1614,9 @@ static struct virtqueue *vring_create_virtqueue_packed(
                !context;
        vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
 
+       if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
+               vq->weak_barriers = false;
+
        vq->packed.ring_dma_addr = ring_dma_addr;
        vq->packed.driver_event_dma_addr = driver_event_dma_addr;
        vq->packed.device_event_dma_addr = device_event_dma_addr;
@@ -2079,6 +2087,9 @@ struct virtqueue *__vring_new_virtqueue(unsigned int index,
                !context;
        vq->event = virtio_has_feature(vdev, VIRTIO_RING_F_EVENT_IDX);
 
+       if (virtio_has_feature(vdev, VIRTIO_F_ORDER_PLATFORM))
+               vq->weak_barriers = false;
+
        vq->split.queue_dma_addr = 0;
        vq->split.queue_size_in_bytes = 0;
 
@@ -2213,6 +2224,8 @@ void vring_transport_features(struct virtio_device *vdev)
                        break;
                case VIRTIO_F_RING_PACKED:
                        break;
+               case VIRTIO_F_ORDER_PLATFORM:
+                       break;
                default:
                        /* We don't understand this bit. */
                        __virtio_clear_bit(vdev, i);
index 5c4a764..81208cd 100644 (file)
@@ -17,6 +17,7 @@
 #include <linux/watchdog.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
 
 #include <asm/mach-ralink/ralink_regs.h>
 
index 98967f0..db7c57d 100644 (file)
@@ -18,6 +18,7 @@
 #include <linux/watchdog.h>
 #include <linux/moduleparam.h>
 #include <linux/platform_device.h>
+#include <linux/mod_devicetable.h>
 
 #include <asm/mach-ralink/ralink_regs.h>
 
index 0d3a0fb..5294120 100644 (file)
@@ -79,13 +79,13 @@ static int tqmx86_wdt_probe(struct platform_device *pdev)
                return -ENOMEM;
 
        res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-       if (IS_ERR(res))
-               return PTR_ERR(res);
+       if (!res)
+               return -ENODEV;
 
        priv->io_base = devm_ioport_map(&pdev->dev, res->start,
                                        resource_size(res));
-       if (IS_ERR(priv->io_base))
-               return PTR_ERR(priv->io_base);
+       if (!priv->io_base)
+               return -ENOMEM;
 
        watchdog_set_drvdata(&priv->wdd, priv);
 
index 93194f3..117e76b 100644 (file)
@@ -1650,7 +1650,7 @@ void xen_callback_vector(void)
                        xen_have_vector_callback = 0;
                        return;
                }
-               pr_info("Xen HVM callback vector for event delivery is enabled\n");
+               pr_info_once("Xen HVM callback vector for event delivery is enabled\n");
                alloc_intr_gate(HYPERVISOR_CALLBACK_VECTOR,
                                xen_hvm_callback_vector);
        }
index 2e5d845..7aa64d1 100644 (file)
@@ -160,9 +160,10 @@ static void pvcalls_conn_back_read(void *opaque)
 
        /* write the data, then modify the indexes */
        virt_wmb();
-       if (ret < 0)
+       if (ret < 0) {
+               atomic_set(&map->read, 0);
                intf->in_error = ret;
-       else
+       else
                intf->in_prod = prod + ret;
        /* update the indexes, then notify the other end */
        virt_wmb();
@@ -282,13 +283,11 @@ static int pvcalls_back_socket(struct xenbus_device *dev,
 static void pvcalls_sk_state_change(struct sock *sock)
 {
        struct sock_mapping *map = sock->sk_user_data;
-       struct pvcalls_data_intf *intf;
 
        if (map == NULL)
                return;
 
-       intf = map->ring;
-       intf->in_error = -ENOTCONN;
+       atomic_inc(&map->read);
        notify_remote_via_irq(map->irq);
 }
 
index 77224d8..8a249c9 100644 (file)
 #define PVCALLS_NR_RSP_PER_RING __CONST_RING_SIZE(xen_pvcalls, XEN_PAGE_SIZE)
 #define PVCALLS_FRONT_MAX_SPIN 5000
 
+static struct proto pvcalls_proto = {
+       .name   = "PVCalls",
+       .owner  = THIS_MODULE,
+       .obj_size = sizeof(struct sock),
+};
+
 struct pvcalls_bedata {
        struct xen_pvcalls_front_ring ring;
        grant_ref_t ref;
@@ -335,6 +341,42 @@ int pvcalls_front_socket(struct socket *sock)
        return ret;
 }
 
+static void free_active_ring(struct sock_mapping *map)
+{
+       if (!map->active.ring)
+               return;
+
+       free_pages((unsigned long)map->active.data.in,
+                       map->active.ring->ring_order);
+       free_page((unsigned long)map->active.ring);
+}
+
+static int alloc_active_ring(struct sock_mapping *map)
+{
+       void *bytes;
+
+       map->active.ring = (struct pvcalls_data_intf *)
+               get_zeroed_page(GFP_KERNEL);
+       if (!map->active.ring)
+               goto out;
+
+       map->active.ring->ring_order = PVCALLS_RING_ORDER;
+       bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
+                                       PVCALLS_RING_ORDER);
+       if (!bytes)
+               goto out;
+
+       map->active.data.in = bytes;
+       map->active.data.out = bytes +
+               XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER);
+
+       return 0;
+
+out:
+       free_active_ring(map);
+       return -ENOMEM;
+}
+
 static int create_active(struct sock_mapping *map, int *evtchn)
 {
        void *bytes;
@@ -343,15 +385,7 @@ static int create_active(struct sock_mapping *map, int *evtchn)
        *evtchn = -1;
        init_waitqueue_head(&map->active.inflight_conn_req);
 
-       map->active.ring = (struct pvcalls_data_intf *)
-               __get_free_page(GFP_KERNEL | __GFP_ZERO);
-       if (map->active.ring == NULL)
-               goto out_error;
-       map->active.ring->ring_order = PVCALLS_RING_ORDER;
-       bytes = (void *)__get_free_pages(GFP_KERNEL | __GFP_ZERO,
-                                       PVCALLS_RING_ORDER);
-       if (bytes == NULL)
-               goto out_error;
+       bytes = map->active.data.in;
        for (i = 0; i < (1 << PVCALLS_RING_ORDER); i++)
                map->active.ring->ref[i] = gnttab_grant_foreign_access(
                        pvcalls_front_dev->otherend_id,
@@ -361,10 +395,6 @@ static int create_active(struct sock_mapping *map, int *evtchn)
                pvcalls_front_dev->otherend_id,
                pfn_to_gfn(virt_to_pfn((void *)map->active.ring)), 0);
 
-       map->active.data.in = bytes;
-       map->active.data.out = bytes +
-               XEN_FLEX_RING_SIZE(PVCALLS_RING_ORDER);
-
        ret = xenbus_alloc_evtchn(pvcalls_front_dev, evtchn);
        if (ret)
                goto out_error;
@@ -385,8 +415,6 @@ static int create_active(struct sock_mapping *map, int *evtchn)
 out_error:
        if (*evtchn >= 0)
                xenbus_free_evtchn(pvcalls_front_dev, *evtchn);
-       free_pages((unsigned long)map->active.data.in, PVCALLS_RING_ORDER);
-       free_page((unsigned long)map->active.ring);
        return ret;
 }
 
@@ -406,17 +434,24 @@ int pvcalls_front_connect(struct socket *sock, struct sockaddr *addr,
                return PTR_ERR(map);
 
        bedata = dev_get_drvdata(&pvcalls_front_dev->dev);
+       ret = alloc_active_ring(map);
+       if (ret < 0) {
+               pvcalls_exit_sock(sock);
+               return ret;
+       }
 
        spin_lock(&bedata->socket_lock);
        ret = get_request(bedata, &req_id);
        if (ret < 0) {
                spin_unlock(&bedata->socket_lock);
+               free_active_ring(map);
                pvcalls_exit_sock(sock);
                return ret;
        }
        ret = create_active(map, &evtchn);
        if (ret < 0) {
                spin_unlock(&bedata->socket_lock);
+               free_active_ring(map);
                pvcalls_exit_sock(sock);
                return ret;
        }
@@ -469,8 +504,10 @@ static int __write_ring(struct pvcalls_data_intf *intf,
        virt_mb();
 
        size = pvcalls_queued(prod, cons, array_size);
-       if (size >= array_size)
+       if (size > array_size)
                return -EINVAL;
+       if (size == array_size)
+               return 0;
        if (len > array_size - size)
                len = array_size - size;
 
@@ -560,15 +597,13 @@ static int __read_ring(struct pvcalls_data_intf *intf,
        error = intf->in_error;
        /* get pointers before reading from the ring */
        virt_rmb();
-       if (error < 0)
-               return error;
 
        size = pvcalls_queued(prod, cons, array_size);
        masked_prod = pvcalls_mask(prod, array_size);
        masked_cons = pvcalls_mask(cons, array_size);
 
        if (size == 0)
-               return 0;
+               return error ?: size;
 
        if (len > size)
                len = size;
@@ -780,25 +815,36 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
                }
        }
 
-       spin_lock(&bedata->socket_lock);
-       ret = get_request(bedata, &req_id);
-       if (ret < 0) {
+       map2 = kzalloc(sizeof(*map2), GFP_KERNEL);
+       if (map2 == NULL) {
                clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
                          (void *)&map->passive.flags);
-               spin_unlock(&bedata->socket_lock);
+               pvcalls_exit_sock(sock);
+               return -ENOMEM;
+       }
+       ret = alloc_active_ring(map2);
+       if (ret < 0) {
+               clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
+                               (void *)&map->passive.flags);
+               kfree(map2);
                pvcalls_exit_sock(sock);
                return ret;
        }
-       map2 = kzalloc(sizeof(*map2), GFP_ATOMIC);
-       if (map2 == NULL) {
+       spin_lock(&bedata->socket_lock);
+       ret = get_request(bedata, &req_id);
+       if (ret < 0) {
                clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
                          (void *)&map->passive.flags);
                spin_unlock(&bedata->socket_lock);
+               free_active_ring(map2);
+               kfree(map2);
                pvcalls_exit_sock(sock);
-               return -ENOMEM;
+               return ret;
        }
+
        ret = create_active(map2, &evtchn);
        if (ret < 0) {
+               free_active_ring(map2);
                kfree(map2);
                clear_bit(PVCALLS_FLAG_ACCEPT_INFLIGHT,
                          (void *)&map->passive.flags);
@@ -839,7 +885,7 @@ int pvcalls_front_accept(struct socket *sock, struct socket *newsock, int flags)
 
 received:
        map2->sock = newsock;
-       newsock->sk = kzalloc(sizeof(*newsock->sk), GFP_KERNEL);
+       newsock->sk = sk_alloc(sock_net(sock->sk), PF_INET, GFP_KERNEL, &pvcalls_proto, false);
        if (!newsock->sk) {
                bedata->rsp[req_id].req_id = PVCALLS_INVALID_ID;
                map->passive.inflight_req_id = PVCALLS_INVALID_ID;
@@ -1032,8 +1078,8 @@ int pvcalls_front_release(struct socket *sock)
                spin_lock(&bedata->socket_lock);
                list_del(&map->list);
                spin_unlock(&bedata->socket_lock);
-               if (READ_ONCE(map->passive.inflight_req_id) !=
-                   PVCALLS_INVALID_ID) {
+               if (READ_ONCE(map->passive.inflight_req_id) != PVCALLS_INVALID_ID &&
+                       READ_ONCE(map->passive.inflight_req_id) != 0) {
                        pvcalls_front_free_map(bedata,
                                               map->passive.accept_map);
                }
index 989cf87..bb78884 100644 (file)
@@ -645,7 +645,7 @@ xen_swiotlb_dma_mmap(struct device *dev, struct vm_area_struct *vma,
                     void *cpu_addr, dma_addr_t dma_addr, size_t size,
                     unsigned long attrs)
 {
-#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#ifdef CONFIG_ARM
        if (xen_get_dma_ops(dev)->mmap)
                return xen_get_dma_ops(dev)->mmap(dev, vma, cpu_addr,
                                                    dma_addr, size, attrs);
@@ -662,7 +662,7 @@ xen_swiotlb_get_sgtable(struct device *dev, struct sg_table *sgt,
                        void *cpu_addr, dma_addr_t handle, size_t size,
                        unsigned long attrs)
 {
-#if defined(CONFIG_ARM) || defined(CONFIG_ARM64)
+#ifdef CONFIG_ARM
        if (xen_get_dma_ops(dev)->get_sgtable) {
 #if 0
        /*
index 0568fd9..e432bd2 100644 (file)
@@ -208,7 +208,7 @@ again:
                /* The new front of the queue now owns the state variables. */
                next = list_entry(vnode->pending_locks.next,
                                  struct file_lock, fl_u.afs.link);
-               vnode->lock_key = afs_file_key(next->fl_file);
+               vnode->lock_key = key_get(afs_file_key(next->fl_file));
                vnode->lock_type = (next->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE;
                vnode->lock_state = AFS_VNODE_LOCK_WAITING_FOR_CB;
                goto again;
@@ -413,7 +413,7 @@ static void afs_dequeue_lock(struct afs_vnode *vnode, struct file_lock *fl)
        /* The new front of the queue now owns the state variables. */
        next = list_entry(vnode->pending_locks.next,
                          struct file_lock, fl_u.afs.link);
-       vnode->lock_key = afs_file_key(next->fl_file);
+       vnode->lock_key = key_get(afs_file_key(next->fl_file));
        vnode->lock_type = (next->fl_type == F_RDLCK) ? AFS_LOCK_READ : AFS_LOCK_WRITE;
        vnode->lock_state = AFS_VNODE_LOCK_WAITING_FOR_CB;
        afs_lock_may_be_available(vnode);
index 6b17d36..1a4ce07 100644 (file)
@@ -414,7 +414,6 @@ int afs_validate(struct afs_vnode *vnode, struct key *key)
        } else if (test_bit(AFS_VNODE_DELETED, &vnode->flags)) {
                valid = true;
        } else {
-               vnode->cb_s_break = vnode->cb_interest->server->cb_s_break;
                vnode->cb_v_break = vnode->volume->cb_v_break;
                valid = false;
        }
@@ -546,6 +545,8 @@ void afs_evict_inode(struct inode *inode)
 #endif
 
        afs_put_permits(rcu_access_pointer(vnode->permit_cache));
+       key_put(vnode->lock_key);
+       vnode->lock_key = NULL;
        _leave("");
 }
 
index 07bc10f..d443e2b 100644 (file)
@@ -161,3 +161,14 @@ struct yfs_xdr_YFSStoreVolumeStatus {
        struct yfs_xdr_u64      max_quota;
        struct yfs_xdr_u64      file_quota;
 } __packed;
+
+enum yfs_lock_type {
+       yfs_LockNone            = -1,
+       yfs_LockRead            = 0,
+       yfs_LockWrite           = 1,
+       yfs_LockExtend          = 2,
+       yfs_LockRelease         = 3,
+       yfs_LockMandatoryRead   = 0x100,
+       yfs_LockMandatoryWrite  = 0x101,
+       yfs_LockMandatoryExtend = 0x102,
+};
index a7b4486..2c588f9 100644 (file)
@@ -23,6 +23,7 @@ struct workqueue_struct *afs_async_calls;
 static void afs_wake_up_call_waiter(struct sock *, struct rxrpc_call *, unsigned long);
 static long afs_wait_for_call_to_complete(struct afs_call *, struct afs_addr_cursor *);
 static void afs_wake_up_async_call(struct sock *, struct rxrpc_call *, unsigned long);
+static void afs_delete_async_call(struct work_struct *);
 static void afs_process_async_call(struct work_struct *);
 static void afs_rx_new_call(struct sock *, struct rxrpc_call *, unsigned long);
 static void afs_rx_discard_new_call(struct rxrpc_call *, unsigned long);
@@ -203,20 +204,26 @@ void afs_put_call(struct afs_call *call)
        }
 }
 
+static struct afs_call *afs_get_call(struct afs_call *call,
+                                    enum afs_call_trace why)
+{
+       int u = atomic_inc_return(&call->usage);
+
+       trace_afs_call(call, why, u,
+                      atomic_read(&call->net->nr_outstanding_calls),
+                      __builtin_return_address(0));
+       return call;
+}
+
 /*
  * Queue the call for actual work.
  */
 static void afs_queue_call_work(struct afs_call *call)
 {
        if (call->type->work) {
-               int u = atomic_inc_return(&call->usage);
-
-               trace_afs_call(call, afs_call_trace_work, u,
-                              atomic_read(&call->net->nr_outstanding_calls),
-                              __builtin_return_address(0));
-
                INIT_WORK(&call->work, call->type->work);
 
+               afs_get_call(call, afs_call_trace_work);
                if (!queue_work(afs_wq, &call->work))
                        afs_put_call(call);
        }
@@ -398,6 +405,12 @@ long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call,
                }
        }
 
+       /* If the call is going to be asynchronous, we need an extra ref for
+        * the call to hold itself so the caller need not hang on to its ref.
+        */
+       if (call->async)
+               afs_get_call(call, afs_call_trace_get);
+
        /* create a call */
        rxcall = rxrpc_kernel_begin_call(call->net->socket, srx, call->key,
                                         (unsigned long)call,
@@ -438,15 +451,17 @@ long afs_make_call(struct afs_addr_cursor *ac, struct afs_call *call,
                        goto error_do_abort;
        }
 
-       /* at this point, an async call may no longer exist as it may have
-        * already completed */
-       if (call->async)
+       /* Note that at this point, we may have received the reply or an abort
+        * - and an asynchronous call may already have completed.
+        */
+       if (call->async) {
+               afs_put_call(call);
                return -EINPROGRESS;
+       }
 
        return afs_wait_for_call_to_complete(call, ac);
 
 error_do_abort:
-       call->state = AFS_CALL_COMPLETE;
        if (ret != -ECONNABORTED) {
                rxrpc_kernel_abort_call(call->net->socket, rxcall,
                                        RX_USER_ABORT, ret, "KSD");
@@ -463,8 +478,24 @@ error_do_abort:
 error_kill_call:
        if (call->type->done)
                call->type->done(call);
-       afs_put_call(call);
+
+       /* We need to dispose of the extra ref we grabbed for an async call.
+        * The call, however, might be queued on afs_async_calls and we need to
+        * make sure we don't get any more notifications that might requeue it.
+        */
+       if (call->rxcall) {
+               rxrpc_kernel_end_call(call->net->socket, call->rxcall);
+               call->rxcall = NULL;
+       }
+       if (call->async) {
+               if (cancel_work_sync(&call->async_work))
+                       afs_put_call(call);
+               afs_put_call(call);
+       }
+
        ac->error = ret;
+       call->state = AFS_CALL_COMPLETE;
+       afs_put_call(call);
        _leave(" = %d", ret);
        return ret;
 }
index 95d0761..155dc14 100644 (file)
@@ -42,9 +42,7 @@ struct afs_server_list *afs_alloc_server_list(struct afs_cell *cell,
                if (vldb->fs_mask[i] & type_mask)
                        nr_servers++;
 
-       slist = kzalloc(sizeof(struct afs_server_list) +
-                       sizeof(struct afs_server_entry) * nr_servers,
-                       GFP_KERNEL);
+       slist = kzalloc(struct_size(slist, servers, nr_servers), GFP_KERNEL);
        if (!slist)
                goto error;
 
index 12658c1..5aa5792 100644 (file)
@@ -803,7 +803,7 @@ int yfs_fs_create_file(struct afs_fs_cursor *fc,
        bp = xdr_encode_YFSFid(bp, &vnode->fid);
        bp = xdr_encode_string(bp, name, namesz);
        bp = xdr_encode_YFSStoreStatus_mode(bp, mode);
-       bp = xdr_encode_u32(bp, 0); /* ViceLockType */
+       bp = xdr_encode_u32(bp, yfs_LockNone); /* ViceLockType */
        yfs_check_req(call, bp);
 
        afs_use_fs_server(call, fc->cbi);
index b906ff7..aaaaf4d 100644 (file)
--- a/fs/aio.c
+++ b/fs/aio.c
@@ -1436,6 +1436,7 @@ static int aio_prep_rw(struct kiocb *req, const struct iocb *iocb)
        if (unlikely(!req->ki_filp))
                return -EBADF;
        req->ki_complete = aio_complete_rw;
+       req->private = NULL;
        req->ki_pos = iocb->aio_offset;
        req->ki_flags = iocb_flags(req->ki_filp);
        if (iocb->aio_flags & IOCB_FLAG_RESFD)
index d441244..28d9c2b 100644 (file)
@@ -596,7 +596,6 @@ int autofs_expire_run(struct super_block *sb,
        pkt.len = dentry->d_name.len;
        memcpy(pkt.name, dentry->d_name.name, pkt.len);
        pkt.name[pkt.len] = '\0';
-       dput(dentry);
 
        if (copy_to_user(pkt_p, &pkt, sizeof(struct autofs_packet_expire)))
                ret = -EFAULT;
@@ -609,6 +608,8 @@ int autofs_expire_run(struct super_block *sb,
        complete_all(&ino->expire_complete);
        spin_unlock(&sbi->fs_lock);
 
+       dput(dentry);
+
        return ret;
 }
 
index 0e8ea2d..078992e 100644 (file)
@@ -266,8 +266,10 @@ int autofs_fill_super(struct super_block *s, void *data, int silent)
        }
        root_inode = autofs_get_inode(s, S_IFDIR | 0755);
        root = d_make_root(root_inode);
-       if (!root)
+       if (!root) {
+               ret = -ENOMEM;
                goto fail_ino;
+       }
        pipe = NULL;
 
        root->d_fsdata = ino;
index d0078cb..e996174 100644 (file)
 #include <linux/err.h>
 #include <linux/fs.h>
 
+static inline bool spacetab(char c) { return c == ' ' || c == '\t'; }
+static inline char *next_non_spacetab(char *first, const char *last)
+{
+       for (; first <= last; first++)
+               if (!spacetab(*first))
+                       return first;
+       return NULL;
+}
+static inline char *next_terminator(char *first, const char *last)
+{
+       for (; first <= last; first++)
+               if (spacetab(*first) || !*first)
+                       return first;
+       return NULL;
+}
+
 static int load_script(struct linux_binprm *bprm)
 {
        const char *i_arg, *i_name;
-       char *cp;
+       char *cp, *buf_end;
        struct file *file;
        int retval;
 
+       /* Not ours to exec if we don't start with "#!". */
        if ((bprm->buf[0] != '#') || (bprm->buf[1] != '!'))
                return -ENOEXEC;
 
@@ -33,23 +50,41 @@ static int load_script(struct linux_binprm *bprm)
        if (bprm->interp_flags & BINPRM_FLAGS_PATH_INACCESSIBLE)
                return -ENOENT;
 
-       /*
-        * This section does the #! interpretation.
-        * Sorta complicated, but hopefully it will work.  -TYT
-        */
-
+       /* Release since we are not mapping a binary into memory. */
        allow_write_access(bprm->file);
        fput(bprm->file);
        bprm->file = NULL;
 
-       for (cp = bprm->buf+2;; cp++) {
-               if (cp >= bprm->buf + BINPRM_BUF_SIZE)
+       /*
+        * This section handles parsing the #! line into separate
+        * interpreter path and argument strings. We must be careful
+        * because bprm->buf is not yet guaranteed to be NUL-terminated
+        * (though the buffer will have trailing NUL padding when the
+        * file size was smaller than the buffer size).
+        *
+        * We do not want to exec a truncated interpreter path, so either
+        * we find a newline (which indicates nothing is truncated), or
+        * we find a space/tab/NUL after the interpreter path (which
+        * itself may be preceded by spaces/tabs). Truncating the
+        * arguments is fine: the interpreter can re-read the script to
+        * parse them on its own.
+        */
+       buf_end = bprm->buf + sizeof(bprm->buf) - 1;
+       cp = strnchr(bprm->buf, sizeof(bprm->buf), '\n');
+       if (!cp) {
+               cp = next_non_spacetab(bprm->buf + 2, buf_end);
+               if (!cp)
+                       return -ENOEXEC; /* Entire buf is spaces/tabs */
+               /*
+                * If there is no later space/tab/NUL we must assume the
+                * interpreter path is truncated.
+                */
+               if (!next_terminator(cp, buf_end))
                        return -ENOEXEC;
-               if (!*cp || (*cp == '\n'))
-                       break;
+               cp = buf_end;
        }
+       /* NUL-terminate the buffer and any trailing spaces/tabs. */
        *cp = '\0';
-
        while (cp > bprm->buf) {
                cp--;
                if ((*cp == ' ') || (*cp == '\t'))
index c546cdc..58a4c12 100644 (file)
@@ -104,6 +104,20 @@ void invalidate_bdev(struct block_device *bdev)
 }
 EXPORT_SYMBOL(invalidate_bdev);
 
+static void set_init_blocksize(struct block_device *bdev)
+{
+       unsigned bsize = bdev_logical_block_size(bdev);
+       loff_t size = i_size_read(bdev->bd_inode);
+
+       while (bsize < PAGE_SIZE) {
+               if (size & bsize)
+                       break;
+               bsize <<= 1;
+       }
+       bdev->bd_block_size = bsize;
+       bdev->bd_inode->i_blkbits = blksize_bits(bsize);
+}
+
 int set_blocksize(struct block_device *bdev, int size)
 {
        /* Size must be a power of two, and between 512 and PAGE_SIZE */
@@ -1431,18 +1445,9 @@ EXPORT_SYMBOL(check_disk_change);
 
 void bd_set_size(struct block_device *bdev, loff_t size)
 {
-       unsigned bsize = bdev_logical_block_size(bdev);
-
        inode_lock(bdev->bd_inode);
        i_size_write(bdev->bd_inode, size);
        inode_unlock(bdev->bd_inode);
-       while (bsize < PAGE_SIZE) {
-               if (size & bsize)
-                       break;
-               bsize <<= 1;
-       }
-       bdev->bd_block_size = bsize;
-       bdev->bd_inode->i_blkbits = blksize_bits(bsize);
 }
 EXPORT_SYMBOL(bd_set_size);
 
@@ -1519,8 +1524,10 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                                }
                        }
 
-                       if (!ret)
+                       if (!ret) {
                                bd_set_size(bdev,(loff_t)get_capacity(disk)<<9);
+                               set_init_blocksize(bdev);
+                       }
 
                        /*
                         * If the device is invalidated, rescan partition
@@ -1555,6 +1562,7 @@ static int __blkdev_get(struct block_device *bdev, fmode_t mode, int for_part)
                                goto out_clear;
                        }
                        bd_set_size(bdev, (loff_t)bdev->bd_part->nr_sects << 9);
+                       set_init_blocksize(bdev);
                }
 
                if (bdev->bd_bdi == &noop_backing_dev_info)
index d92462f..5a6c39b 100644 (file)
@@ -968,6 +968,48 @@ static noinline int update_ref_for_cow(struct btrfs_trans_handle *trans,
        return 0;
 }
 
+static struct extent_buffer *alloc_tree_block_no_bg_flush(
+                                         struct btrfs_trans_handle *trans,
+                                         struct btrfs_root *root,
+                                         u64 parent_start,
+                                         const struct btrfs_disk_key *disk_key,
+                                         int level,
+                                         u64 hint,
+                                         u64 empty_size)
+{
+       struct btrfs_fs_info *fs_info = root->fs_info;
+       struct extent_buffer *ret;
+
+       /*
+        * If we are COWing a node/leaf from the extent, chunk, device or free
+        * space trees, make sure that we do not finish block group creation of
+        * pending block groups. We do this to avoid a deadlock.
+        * COWing can result in allocation of a new chunk, and flushing pending
+        * block groups (btrfs_create_pending_block_groups()) can be triggered
+        * when finishing allocation of a new chunk. Creation of a pending block
+        * group modifies the extent, chunk, device and free space trees,
+        * therefore we could deadlock with ourselves since we are holding a
+        * lock on an extent buffer that btrfs_create_pending_block_groups() may
+        * try to COW later.
+        * For similar reasons, we also need to delay flushing pending block
+        * groups when splitting a leaf or node, from one of those trees, since
+        * we are holding a write lock on it and its parent or when inserting a
+        * new root node for one of those trees.
+        */
+       if (root == fs_info->extent_root ||
+           root == fs_info->chunk_root ||
+           root == fs_info->dev_root ||
+           root == fs_info->free_space_root)
+               trans->can_flush_pending_bgs = false;
+
+       ret = btrfs_alloc_tree_block(trans, root, parent_start,
+                                    root->root_key.objectid, disk_key, level,
+                                    hint, empty_size);
+       trans->can_flush_pending_bgs = true;
+
+       return ret;
+}
+
 /*
  * does the dirty work in cow of a single block.  The parent block (if
  * supplied) is updated to point to the new cow copy.  The new buffer is marked
@@ -1015,26 +1057,8 @@ static noinline int __btrfs_cow_block(struct btrfs_trans_handle *trans,
        if ((root->root_key.objectid == BTRFS_TREE_RELOC_OBJECTID) && parent)
                parent_start = parent->start;
 
-       /*
-        * If we are COWing a node/leaf from the extent, chunk or device trees,
-        * make sure that we do not finish block group creation of pending block
-        * groups. We do this to avoid a deadlock.
-        * COWing can result in allocation of a new chunk, and flushing pending
-        * block groups (btrfs_create_pending_block_groups()) can be triggered
-        * when finishing allocation of a new chunk. Creation of a pending block
-        * group modifies the extent, chunk and device trees, therefore we could
-        * deadlock with ourselves since we are holding a lock on an extent
-        * buffer that btrfs_create_pending_block_groups() may try to COW later.
-        */
-       if (root == fs_info->extent_root ||
-           root == fs_info->chunk_root ||
-           root == fs_info->dev_root)
-               trans->can_flush_pending_bgs = false;
-
-       cow = btrfs_alloc_tree_block(trans, root, parent_start,
-                       root->root_key.objectid, &disk_key, level,
-                       search_start, empty_size);
-       trans->can_flush_pending_bgs = true;
+       cow = alloc_tree_block_no_bg_flush(trans, root, parent_start, &disk_key,
+                                          level, search_start, empty_size);
        if (IS_ERR(cow))
                return PTR_ERR(cow);
 
@@ -3343,8 +3367,8 @@ static noinline int insert_new_root(struct btrfs_trans_handle *trans,
        else
                btrfs_node_key(lower, &lower_key, 0);
 
-       c = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid,
-                                  &lower_key, level, root->node->start, 0);
+       c = alloc_tree_block_no_bg_flush(trans, root, 0, &lower_key, level,
+                                        root->node->start, 0);
        if (IS_ERR(c))
                return PTR_ERR(c);
 
@@ -3473,8 +3497,8 @@ static noinline int split_node(struct btrfs_trans_handle *trans,
        mid = (c_nritems + 1) / 2;
        btrfs_node_key(c, &disk_key, mid);
 
-       split = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid,
-                       &disk_key, level, c->start, 0);
+       split = alloc_tree_block_no_bg_flush(trans, root, 0, &disk_key, level,
+                                            c->start, 0);
        if (IS_ERR(split))
                return PTR_ERR(split);
 
@@ -4258,8 +4282,8 @@ again:
        else
                btrfs_item_key(l, &disk_key, mid);
 
-       right = btrfs_alloc_tree_block(trans, root, 0, root->root_key.objectid,
-                       &disk_key, 0, l->start, 0);
+       right = alloc_tree_block_no_bg_flush(trans, root, 0, &disk_key, 0,
+                                            l->start, 0);
        if (IS_ERR(right))
                return PTR_ERR(right);
 
index 0a68cf7..7a2a262 100644 (file)
@@ -35,6 +35,7 @@
 struct btrfs_trans_handle;
 struct btrfs_transaction;
 struct btrfs_pending_snapshot;
+struct btrfs_delayed_ref_root;
 extern struct kmem_cache *btrfs_trans_handle_cachep;
 extern struct kmem_cache *btrfs_bit_radix_cachep;
 extern struct kmem_cache *btrfs_path_cachep;
@@ -786,6 +787,9 @@ enum {
         * main phase. The fs_info::balance_ctl is initialized.
         */
        BTRFS_FS_BALANCE_RUNNING,
+
+       /* Indicate that the cleaner thread is awake and doing something. */
+       BTRFS_FS_CLEANER_RUNNING,
 };
 
 struct btrfs_fs_info {
@@ -2661,6 +2665,9 @@ int btrfs_run_delayed_refs(struct btrfs_trans_handle *trans,
                           unsigned long count);
 int btrfs_async_run_delayed_refs(struct btrfs_fs_info *fs_info,
                                 unsigned long count, u64 transid, int wait);
+void btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
+                                 struct btrfs_delayed_ref_root *delayed_refs,
+                                 struct btrfs_delayed_ref_head *head);
 int btrfs_lookup_data_extent(struct btrfs_fs_info *fs_info, u64 start, u64 len);
 int btrfs_lookup_extent_info(struct btrfs_trans_handle *trans,
                             struct btrfs_fs_info *fs_info, u64 bytenr,
index 8da2f38..6a2a2a9 100644 (file)
@@ -1682,6 +1682,8 @@ static int cleaner_kthread(void *arg)
        while (1) {
                again = 0;
 
+               set_bit(BTRFS_FS_CLEANER_RUNNING, &fs_info->flags);
+
                /* Make the cleaner go to sleep early. */
                if (btrfs_need_cleaner_sleep(fs_info))
                        goto sleep;
@@ -1728,6 +1730,7 @@ static int cleaner_kthread(void *arg)
                 */
                btrfs_delete_unused_bgs(fs_info);
 sleep:
+               clear_bit(BTRFS_FS_CLEANER_RUNNING, &fs_info->flags);
                if (kthread_should_park())
                        kthread_parkme();
                if (kthread_should_stop())
@@ -4201,6 +4204,14 @@ static void btrfs_destroy_all_ordered_extents(struct btrfs_fs_info *fs_info)
                spin_lock(&fs_info->ordered_root_lock);
        }
        spin_unlock(&fs_info->ordered_root_lock);
+
+       /*
+        * We need this here because if we've been flipped read-only we won't
+        * get sync() from the umount, so we need to make sure any ordered
+        * extents that haven't had their dirty pages IO start writeout yet
+        * actually get run and error out properly.
+        */
+       btrfs_wait_ordered_roots(fs_info, U64_MAX, 0, (u64)-1);
 }
 
 static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
@@ -4265,6 +4276,7 @@ static int btrfs_destroy_delayed_refs(struct btrfs_transaction *trans,
                if (pin_bytes)
                        btrfs_pin_extent(fs_info, head->bytenr,
                                         head->num_bytes, 1);
+               btrfs_cleanup_ref_head_accounting(fs_info, delayed_refs, head);
                btrfs_put_delayed_ref_head(head);
                cond_resched();
                spin_lock(&delayed_refs->lock);
index b15afea..d81035b 100644 (file)
@@ -2456,12 +2456,10 @@ static int run_and_cleanup_extent_op(struct btrfs_trans_handle *trans,
        return ret ? ret : 1;
 }
 
-static void cleanup_ref_head_accounting(struct btrfs_trans_handle *trans,
-                                       struct btrfs_delayed_ref_head *head)
+void btrfs_cleanup_ref_head_accounting(struct btrfs_fs_info *fs_info,
+                                 struct btrfs_delayed_ref_root *delayed_refs,
+                                 struct btrfs_delayed_ref_head *head)
 {
-       struct btrfs_fs_info *fs_info = trans->fs_info;
-       struct btrfs_delayed_ref_root *delayed_refs =
-               &trans->transaction->delayed_refs;
        int nr_items = 1;       /* Dropping this ref head update. */
 
        if (head->total_ref_mod < 0) {
@@ -2544,7 +2542,7 @@ static int cleanup_ref_head(struct btrfs_trans_handle *trans,
                }
        }
 
-       cleanup_ref_head_accounting(trans, head);
+       btrfs_cleanup_ref_head_accounting(fs_info, delayed_refs, head);
 
        trace_run_delayed_ref_head(fs_info, head, 0);
        btrfs_delayed_ref_unlock(head);
@@ -4954,6 +4952,15 @@ static void flush_space(struct btrfs_fs_info *fs_info,
                        ret = 0;
                break;
        case COMMIT_TRANS:
+               /*
+                * If we have pending delayed iputs then we could free up a
+                * bunch of pinned space, so make sure we run the iputs before
+                * we do our pinned bytes check below.
+                */
+               mutex_lock(&fs_info->cleaner_delayed_iput_mutex);
+               btrfs_run_delayed_iputs(fs_info);
+               mutex_unlock(&fs_info->cleaner_delayed_iput_mutex);
+
                ret = may_commit_transaction(fs_info, space_info);
                break;
        default:
@@ -7188,7 +7195,7 @@ static noinline int check_ref_cleanup(struct btrfs_trans_handle *trans,
        if (head->must_insert_reserved)
                ret = 1;
 
-       cleanup_ref_head_accounting(trans, head);
+       btrfs_cleanup_ref_head_accounting(trans->fs_info, delayed_refs, head);
        mutex_unlock(&head->mutex);
        btrfs_put_delayed_ref_head(head);
        return ret;
index 43eb453..5c34966 100644 (file)
@@ -3129,9 +3129,6 @@ out:
        /* once for the tree */
        btrfs_put_ordered_extent(ordered_extent);
 
-       /* Try to release some metadata so we don't get an OOM but don't wait */
-       btrfs_btree_balance_dirty_nodelay(fs_info);
-
        return ret;
 }
 
@@ -3254,6 +3251,8 @@ void btrfs_add_delayed_iput(struct inode *inode)
        ASSERT(list_empty(&binode->delayed_iput));
        list_add_tail(&binode->delayed_iput, &fs_info->delayed_iputs);
        spin_unlock(&fs_info->delayed_iput_lock);
+       if (!test_bit(BTRFS_FS_CLEANER_RUNNING, &fs_info->flags))
+               wake_up_process(fs_info->cleaner_kthread);
 }
 
 void btrfs_run_delayed_iputs(struct btrfs_fs_info *fs_info)
index fab9443..9c8e173 100644 (file)
@@ -3221,6 +3221,26 @@ static void btrfs_double_inode_lock(struct inode *inode1, struct inode *inode2)
        inode_lock_nested(inode2, I_MUTEX_CHILD);
 }
 
+static void btrfs_double_extent_unlock(struct inode *inode1, u64 loff1,
+                                      struct inode *inode2, u64 loff2, u64 len)
+{
+       unlock_extent(&BTRFS_I(inode1)->io_tree, loff1, loff1 + len - 1);
+       unlock_extent(&BTRFS_I(inode2)->io_tree, loff2, loff2 + len - 1);
+}
+
+static void btrfs_double_extent_lock(struct inode *inode1, u64 loff1,
+                                    struct inode *inode2, u64 loff2, u64 len)
+{
+       if (inode1 < inode2) {
+               swap(inode1, inode2);
+               swap(loff1, loff2);
+       } else if (inode1 == inode2 && loff2 < loff1) {
+               swap(loff1, loff2);
+       }
+       lock_extent(&BTRFS_I(inode1)->io_tree, loff1, loff1 + len - 1);
+       lock_extent(&BTRFS_I(inode2)->io_tree, loff2, loff2 + len - 1);
+}
+
 static int btrfs_extent_same_range(struct inode *src, u64 loff, u64 olen,
                                   struct inode *dst, u64 dst_loff)
 {
@@ -3242,11 +3262,12 @@ static int btrfs_extent_same_range(struct inode *src, u64 loff, u64 olen,
                return -EINVAL;
 
        /*
-        * Lock destination range to serialize with concurrent readpages().
+        * Lock destination range to serialize with concurrent readpages() and
+        * source range to serialize with relocation.
         */
-       lock_extent(&BTRFS_I(dst)->io_tree, dst_loff, dst_loff + len - 1);
+       btrfs_double_extent_lock(src, loff, dst, dst_loff, len);
        ret = btrfs_clone(src, dst, loff, olen, len, dst_loff, 1);
-       unlock_extent(&BTRFS_I(dst)->io_tree, dst_loff, dst_loff + len - 1);
+       btrfs_double_extent_unlock(src, loff, dst, dst_loff, len);
 
        return ret;
 }
@@ -3905,17 +3926,33 @@ static noinline int btrfs_clone_files(struct file *file, struct file *file_src,
                len = ALIGN(src->i_size, bs) - off;
 
        if (destoff > inode->i_size) {
+               const u64 wb_start = ALIGN_DOWN(inode->i_size, bs);
+
                ret = btrfs_cont_expand(inode, inode->i_size, destoff);
                if (ret)
                        return ret;
+               /*
+                * We may have truncated the last block if the inode's size is
+                * not sector size aligned, so we need to wait for writeback to
+                * complete before proceeding further, otherwise we can race
+                * with cloning and attempt to increment a reference to an
+                * extent that no longer exists (writeback completed right after
+                * we found the previous extent covering eof and before we
+                * attempted to increment its reference count).
+                */
+               ret = btrfs_wait_ordered_range(inode, wb_start,
+                                              destoff - wb_start);
+               if (ret)
+                       return ret;
        }
 
        /*
-        * Lock destination range to serialize with concurrent readpages().
+        * Lock destination range to serialize with concurrent readpages() and
+        * source range to serialize with relocation.
         */
-       lock_extent(&BTRFS_I(inode)->io_tree, destoff, destoff + len - 1);
+       btrfs_double_extent_lock(src, off, inode, destoff, len);
        ret = btrfs_clone(src, inode, off, olen, len, destoff, 0);
-       unlock_extent(&BTRFS_I(inode)->io_tree, destoff, destoff + len - 1);
+       btrfs_double_extent_unlock(src, off, inode, destoff, len);
        /*
         * Truncate page cache pages so that future reads will see the cloned
         * data immediately and not the previous data.
index c5586ff..0a3f122 100644 (file)
@@ -1621,6 +1621,7 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
                                flags | SB_RDONLY, device_name, data);
                        if (IS_ERR(mnt_root)) {
                                root = ERR_CAST(mnt_root);
+                               kfree(subvol_name);
                                goto out;
                        }
 
@@ -1630,12 +1631,14 @@ static struct dentry *btrfs_mount(struct file_system_type *fs_type, int flags,
                        if (error < 0) {
                                root = ERR_PTR(error);
                                mntput(mnt_root);
+                               kfree(subvol_name);
                                goto out;
                        }
                }
        }
        if (IS_ERR(mnt_root)) {
                root = ERR_CAST(mnt_root);
+               kfree(subvol_name);
                goto out;
        }
 
index 127fa15..4ec2b66 100644 (file)
@@ -850,14 +850,6 @@ static int __btrfs_end_transaction(struct btrfs_trans_handle *trans,
 
        btrfs_trans_release_chunk_metadata(trans);
 
-       if (lock && should_end_transaction(trans) &&
-           READ_ONCE(cur_trans->state) == TRANS_STATE_RUNNING) {
-               spin_lock(&info->trans_lock);
-               if (cur_trans->state == TRANS_STATE_RUNNING)
-                       cur_trans->state = TRANS_STATE_BLOCKED;
-               spin_unlock(&info->trans_lock);
-       }
-
        if (lock && READ_ONCE(cur_trans->state) == TRANS_STATE_BLOCKED) {
                if (throttle)
                        return btrfs_commit_transaction(trans);
@@ -1879,6 +1871,21 @@ static void cleanup_transaction(struct btrfs_trans_handle *trans, int err)
        kmem_cache_free(btrfs_trans_handle_cachep, trans);
 }
 
+/*
+ * Release reserved delayed ref space of all pending block groups of the
+ * transaction and remove them from the list
+ */
+static void btrfs_cleanup_pending_block_groups(struct btrfs_trans_handle *trans)
+{
+       struct btrfs_fs_info *fs_info = trans->fs_info;
+       struct btrfs_block_group_cache *block_group, *tmp;
+
+       list_for_each_entry_safe(block_group, tmp, &trans->new_bgs, bg_list) {
+               btrfs_delayed_refs_rsv_release(fs_info, 1);
+               list_del_init(&block_group->bg_list);
+       }
+}
+
 static inline int btrfs_start_delalloc_flush(struct btrfs_fs_info *fs_info)
 {
        /*
@@ -2270,6 +2277,7 @@ scrub_continue:
        btrfs_scrub_continue(fs_info);
 cleanup_transaction:
        btrfs_trans_release_metadata(trans);
+       btrfs_cleanup_pending_block_groups(trans);
        btrfs_trans_release_chunk_metadata(trans);
        trans->block_rsv = NULL;
        btrfs_warn(fs_info, "Skipping commit of aborted transaction.");
index 2576b1a..1556192 100644 (file)
@@ -957,11 +957,11 @@ static noinline struct btrfs_device *device_list_add(const char *path,
                else
                        fs_devices = alloc_fs_devices(disk_super->fsid, NULL);
 
-               fs_devices->fsid_change = fsid_change_in_progress;
-
                if (IS_ERR(fs_devices))
                        return ERR_CAST(fs_devices);
 
+               fs_devices->fsid_change = fsid_change_in_progress;
+
                mutex_lock(&fs_devices->device_list_mutex);
                list_add(&fs_devices->fs_list, &fs_uuids);
 
@@ -7825,6 +7825,18 @@ static int verify_one_dev_extent(struct btrfs_fs_info *fs_info,
                ret = -EUCLEAN;
                goto out;
        }
+
+       /* It's possible this device is a dummy for seed device */
+       if (dev->disk_total_bytes == 0) {
+               dev = find_device(fs_info->fs_devices->seed, devid, NULL);
+               if (!dev) {
+                       btrfs_err(fs_info, "failed to find seed devid %llu",
+                                 devid);
+                       ret = -EUCLEAN;
+                       goto out;
+               }
+       }
+
        if (physical_offset + physical_len > dev->disk_total_bytes) {
                btrfs_err(fs_info,
 "dev extent devid %llu physical offset %llu len %llu is beyond device boundary %llu",
index 52d024b..48318fb 100644 (file)
@@ -200,6 +200,7 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
        struct buffer_head *head;
        struct page *page;
        int all_mapped = 1;
+       static DEFINE_RATELIMIT_STATE(last_warned, HZ, 1);
 
        index = block >> (PAGE_SHIFT - bd_inode->i_blkbits);
        page = find_get_page_flags(bd_mapping, index, FGP_ACCESSED);
@@ -227,15 +228,15 @@ __find_get_block_slow(struct block_device *bdev, sector_t block)
         * file io on the block device and getblk.  It gets dealt with
         * elsewhere, don't buffer_error if we had some unmapped buffers
         */
-       if (all_mapped) {
-               printk("__find_get_block_slow() failed. "
-                       "block=%llu, b_blocknr=%llu\n",
-                       (unsigned long long)block,
-                       (unsigned long long)bh->b_blocknr);
-               printk("b_state=0x%08lx, b_size=%zu\n",
-                       bh->b_state, bh->b_size);
-               printk("device %pg blocksize: %d\n", bdev,
-                       1 << bd_inode->i_blkbits);
+       ratelimit_set_flags(&last_warned, RATELIMIT_MSG_ON_RELEASE);
+       if (all_mapped && __ratelimit(&last_warned)) {
+               printk("__find_get_block_slow() failed. block=%llu, "
+                      "b_blocknr=%llu, b_state=0x%08lx, b_size=%zu, "
+                      "device %pg blocksize: %d\n",
+                      (unsigned long long)block,
+                      (unsigned long long)bh->b_blocknr,
+                      bh->b_state, bh->b_size, bdev,
+                      1 << bd_inode->i_blkbits);
        }
 out_unlock:
        spin_unlock(&bd_mapping->private_lock);
index 5d0c05e..a47c541 100644 (file)
@@ -1494,10 +1494,7 @@ static vm_fault_t ceph_filemap_fault(struct vm_fault *vmf)
                if (err < 0 || off >= i_size_read(inode)) {
                        unlock_page(page);
                        put_page(page);
-                       if (err == -ENOMEM)
-                               ret = VM_FAULT_OOM;
-                       else
-                               ret = VM_FAULT_SIGBUS;
+                       ret = vmf_error(err);
                        goto out_inline;
                }
                if (err < PAGE_SIZE)
index 94c026b..bba28a5 100644 (file)
@@ -1035,6 +1035,8 @@ static void drop_inode_snap_realm(struct ceph_inode_info *ci)
        list_del_init(&ci->i_snap_realm_item);
        ci->i_snap_realm_counter++;
        ci->i_snap_realm = NULL;
+       if (realm->ino == ci->i_vino.ino)
+               realm->inode = NULL;
        spin_unlock(&realm->inodes_with_caps_lock);
        ceph_put_snap_realm(ceph_sb_to_client(ci->vfs_inode.i_sb)->mdsc,
                            realm);
index 03f4d24..9455d3a 100644 (file)
@@ -3,19 +3,6 @@
  * quota.c - CephFS quota
  *
  * Copyright (C) 2017-2018 SUSE
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
- *
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- * GNU General Public License for more details.
- *
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, see <http://www.gnu.org/licenses/>.
  */
 
 #include <linux/statfs.h>
index 041c27e..f74193d 100644 (file)
@@ -616,7 +616,8 @@ int __ceph_finish_cap_snap(struct ceph_inode_info *ci,
             capsnap->size);
 
        spin_lock(&mdsc->snap_flush_lock);
-       list_add_tail(&ci->i_snap_flush_item, &mdsc->snap_flush_list);
+       if (list_empty(&ci->i_snap_flush_item))
+               list_add_tail(&ci->i_snap_flush_item, &mdsc->snap_flush_list);
        spin_unlock(&mdsc->snap_flush_lock);
        return 1;  /* caller may want to ceph_flush_snaps */
 }
index 4e9a7cc..da2cd8e 100644 (file)
@@ -530,7 +530,7 @@ static int ceph_show_options(struct seq_file *m, struct dentry *root)
        seq_putc(m, ',');
        pos = m->count;
 
-       ret = ceph_print_client_options(m, fsc->client);
+       ret = ceph_print_client_options(m, fsc->client, false);
        if (ret)
                return ret;
 
@@ -640,7 +640,7 @@ static struct ceph_fs_client *create_fs_client(struct ceph_mount_options *fsopt,
        opt = NULL; /* fsc->client now owns this */
 
        fsc->client->extra_mon_dispatch = extra_mon_dispatch;
-       fsc->client->osdc.abort_on_full = true;
+       ceph_set_opt(fsc->client, ABORT_ON_FULL);
 
        if (!fsopt->mds_namespace) {
                ceph_monc_want_map(&fsc->client->monc, CEPH_SUB_MDSMAP,
index 593fb42..e92a2fe 100644 (file)
@@ -252,6 +252,7 @@ static int cifs_debug_data_proc_show(struct seq_file *m, void *v)
        seq_printf(m, ",ACL");
 #endif
        seq_putc(m, '\n');
+       seq_printf(m, "CIFSMaxBufSize: %d\n", CIFSMaxBufSize);
        seq_printf(m, "Active VFS Requests: %d\n", GlobalTotalActiveXid);
        seq_printf(m, "Servers:");
 
index 26776ed..7652551 100644 (file)
@@ -150,5 +150,5 @@ extern long cifs_ioctl(struct file *filep, unsigned int cmd, unsigned long arg);
 extern const struct export_operations cifs_export_ops;
 #endif /* CONFIG_CIFS_NFSD_EXPORT */
 
-#define CIFS_VERSION   "2.15"
+#define CIFS_VERSION   "2.17"
 #endif                         /* _CIFSFS_H */
index 01ded70..94dbdbe 100644 (file)
@@ -1438,6 +1438,7 @@ struct mid_q_entry {
        int mid_state;  /* wish this were enum but can not pass to wait_event */
        unsigned int mid_flags;
        __le16 command;         /* smb command code */
+       unsigned int optype;    /* operation type */
        bool large_buf:1;       /* if valid response, is pointer to large buf */
        bool multiRsp:1;        /* multiple trans2 responses for one request  */
        bool multiEnd:1;        /* both received */
@@ -1574,6 +1575,25 @@ static inline void free_dfs_info_array(struct dfs_info3_param *param,
        kfree(param);
 }
 
+static inline bool is_interrupt_error(int error)
+{
+       switch (error) {
+       case -EINTR:
+       case -ERESTARTSYS:
+       case -ERESTARTNOHAND:
+       case -ERESTARTNOINTR:
+               return true;
+       }
+       return false;
+}
+
+static inline bool is_retryable_error(int error)
+{
+       if (is_interrupt_error(error) || error == -EAGAIN)
+               return true;
+       return false;
+}
+
 #define   MID_FREE 0
 #define   MID_REQUEST_ALLOCATED 1
 #define   MID_REQUEST_SUBMITTED 2
index b1f49c1..bb54ccf 100644 (file)
@@ -128,24 +128,31 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc,
        int rc;
        struct dfs_cache_tgt_list tl;
        struct dfs_cache_tgt_iterator *it = NULL;
-       char tree[MAX_TREE_SIZE + 1];
+       char *tree;
        const char *tcp_host;
        size_t tcp_host_len;
        const char *dfs_host;
        size_t dfs_host_len;
 
+       tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
+       if (!tree)
+               return -ENOMEM;
+
        if (tcon->ipc) {
-               snprintf(tree, sizeof(tree), "\\\\%s\\IPC$",
+               snprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$",
                         tcon->ses->server->hostname);
-               return CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
+               rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
+               goto out;
        }
 
-       if (!tcon->dfs_path)
-               return CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc);
+       if (!tcon->dfs_path) {
+               rc = CIFSTCon(0, tcon->ses, tcon->treeName, tcon, nlsc);
+               goto out;
+       }
 
        rc = dfs_cache_noreq_find(tcon->dfs_path + 1, NULL, &tl);
        if (rc)
-               return rc;
+               goto out;
 
        extract_unc_hostname(tcon->ses->server->hostname, &tcp_host,
                             &tcp_host_len);
@@ -165,7 +172,7 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc,
                        continue;
                }
 
-               snprintf(tree, sizeof(tree), "\\%s", tgt);
+               snprintf(tree, MAX_TREE_SIZE, "\\%s", tgt);
 
                rc = CIFSTCon(0, tcon->ses, tree, tcon, nlsc);
                if (!rc)
@@ -182,6 +189,8 @@ static int __cifs_reconnect_tcon(const struct nls_table *nlsc,
                        rc = -ENOENT;
        }
        dfs_cache_free_tgts(&tl);
+out:
+       kfree(tree);
        return rc;
 }
 #else
@@ -1540,18 +1549,26 @@ cifs_discard_remaining_data(struct TCP_Server_Info *server)
 }
 
 static int
-cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+__cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid,
+                    bool malformed)
 {
        int length;
-       struct cifs_readdata *rdata = mid->callback_data;
 
        length = cifs_discard_remaining_data(server);
-       dequeue_mid(mid, rdata->result);
+       dequeue_mid(mid, malformed);
        mid->resp_buf = server->smallbuf;
        server->smallbuf = NULL;
        return length;
 }
 
+static int
+cifs_readv_discard(struct TCP_Server_Info *server, struct mid_q_entry *mid)
+{
+       struct cifs_readdata *rdata = mid->callback_data;
+
+       return  __cifs_readv_discard(server, mid, rdata->result);
+}
+
 int
 cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
 {
@@ -1593,12 +1610,23 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
                return -1;
        }
 
+       /* set up first two iov for signature check and to get credits */
+       rdata->iov[0].iov_base = buf;
+       rdata->iov[0].iov_len = 4;
+       rdata->iov[1].iov_base = buf + 4;
+       rdata->iov[1].iov_len = server->total_read - 4;
+       cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
+                rdata->iov[0].iov_base, rdata->iov[0].iov_len);
+       cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
+                rdata->iov[1].iov_base, rdata->iov[1].iov_len);
+
        /* Was the SMB read successful? */
        rdata->result = server->ops->map_error(buf, false);
        if (rdata->result != 0) {
                cifs_dbg(FYI, "%s: server returned error %d\n",
                         __func__, rdata->result);
-               return cifs_readv_discard(server, mid);
+               /* normal error on read response */
+               return __cifs_readv_discard(server, mid, false);
        }
 
        /* Is there enough to get to the rest of the READ_RSP header? */
@@ -1642,14 +1670,6 @@ cifs_readv_receive(struct TCP_Server_Info *server, struct mid_q_entry *mid)
                server->total_read += length;
        }
 
-       /* set up first iov for signature check */
-       rdata->iov[0].iov_base = buf;
-       rdata->iov[0].iov_len = 4;
-       rdata->iov[1].iov_base = buf + 4;
-       rdata->iov[1].iov_len = server->total_read - 4;
-       cifs_dbg(FYI, "0: iov_base=%p iov_len=%u\n",
-                rdata->iov[0].iov_base, server->total_read);
-
        /* how much data is in the response? */
 #ifdef CONFIG_CIFS_SMB_DIRECT
        use_rdma_mr = rdata->mr;
@@ -2114,7 +2134,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
 
                for (j = 0; j < nr_pages; j++) {
                        unlock_page(wdata2->pages[j]);
-                       if (rc != 0 && rc != -EAGAIN) {
+                       if (rc != 0 && !is_retryable_error(rc)) {
                                SetPageError(wdata2->pages[j]);
                                end_page_writeback(wdata2->pages[j]);
                                put_page(wdata2->pages[j]);
@@ -2123,7 +2143,7 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
 
                if (rc) {
                        kref_put(&wdata2->refcount, cifs_writedata_release);
-                       if (rc == -EAGAIN)
+                       if (is_retryable_error(rc))
                                continue;
                        break;
                }
@@ -2132,7 +2152,8 @@ cifs_writev_requeue(struct cifs_writedata *wdata)
                i += nr_pages;
        } while (i < wdata->nr_pages);
 
-       mapping_set_error(inode->i_mapping, rc);
+       if (rc != 0 && !is_retryable_error(rc))
+               mapping_set_error(inode->i_mapping, rc);
        kref_put(&wdata->refcount, cifs_writedata_release);
 }
 
index f665296..8463c94 100644 (file)
@@ -433,9 +433,10 @@ static void reconn_inval_dfs_target(struct TCP_Server_Info *server,
        kfree(server->hostname);
 
        server->hostname = extract_hostname(name);
-       if (!server->hostname) {
-               cifs_dbg(FYI, "%s: failed to extract hostname from target: %d\n",
-                        __func__, -ENOMEM);
+       if (IS_ERR(server->hostname)) {
+               cifs_dbg(FYI,
+                        "%s: failed to extract hostname from target: %ld\n",
+                        __func__, PTR_ERR(server->hostname));
        }
 }
 
@@ -719,6 +720,21 @@ server_unresponsive(struct TCP_Server_Info *server)
        return false;
 }
 
+static inline bool
+zero_credits(struct TCP_Server_Info *server)
+{
+       int val;
+
+       spin_lock(&server->req_lock);
+       val = server->credits + server->echo_credits + server->oplock_credits;
+       if (server->in_flight == 0 && val == 0) {
+               spin_unlock(&server->req_lock);
+               return true;
+       }
+       spin_unlock(&server->req_lock);
+       return false;
+}
+
 static int
 cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
 {
@@ -731,6 +747,12 @@ cifs_readv_from_socket(struct TCP_Server_Info *server, struct msghdr *smb_msg)
        for (total_read = 0; msg_data_left(smb_msg); total_read += length) {
                try_to_freeze();
 
+               /* reconnect if no credits and no requests in flight */
+               if (zero_credits(server)) {
+                       cifs_reconnect(server);
+                       return -ECONNABORTED;
+               }
+
                if (server_unresponsive(server))
                        return -ECONNABORTED;
                if (cifs_rdma_enabled(server) && server->smbd_conn)
index cd63c4a..09b7d0d 100644 (file)
@@ -776,6 +776,7 @@ static int get_tgt_list(const struct dfs_cache_entry *ce,
                it->it_name = kstrndup(t->t_name, strlen(t->t_name),
                                       GFP_KERNEL);
                if (!it->it_name) {
+                       kfree(it);
                        rc = -ENOMEM;
                        goto err_free_it;
                }
index e3e3a75..659ce1b 100644 (file)
@@ -733,7 +733,8 @@ reopen_success:
 
        if (can_flush) {
                rc = filemap_write_and_wait(inode->i_mapping);
-               mapping_set_error(inode->i_mapping, rc);
+               if (!is_interrupt_error(rc))
+                       mapping_set_error(inode->i_mapping, rc);
 
                if (tcon->unix_ext)
                        rc = cifs_get_inode_info_unix(&inode, full_path,
@@ -1132,14 +1133,18 @@ cifs_push_mandatory_locks(struct cifsFileInfo *cfile)
 
        /*
         * Accessing maxBuf is racy with cifs_reconnect - need to store value
-        * and check it for zero before using.
+        * and check it before using.
         */
        max_buf = tcon->ses->server->maxBuf;
-       if (!max_buf) {
+       if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE))) {
                free_xid(xid);
                return -EINVAL;
        }
 
+       BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) >
+                    PAGE_SIZE);
+       max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr),
+                       PAGE_SIZE);
        max_num = (max_buf - sizeof(struct smb_hdr)) /
                                                sizeof(LOCKING_ANDX_RANGE);
        buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
@@ -1472,12 +1477,16 @@ cifs_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
 
        /*
         * Accessing maxBuf is racy with cifs_reconnect - need to store value
-        * and check it for zero before using.
+        * and check it before using.
         */
        max_buf = tcon->ses->server->maxBuf;
-       if (!max_buf)
+       if (max_buf < (sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE)))
                return -EINVAL;
 
+       BUILD_BUG_ON(sizeof(struct smb_hdr) + sizeof(LOCKING_ANDX_RANGE) >
+                    PAGE_SIZE);
+       max_buf = min_t(unsigned int, max_buf - sizeof(struct smb_hdr),
+                       PAGE_SIZE);
        max_num = (max_buf - sizeof(struct smb_hdr)) /
                                                sizeof(LOCKING_ANDX_RANGE);
        buf = kcalloc(max_num, sizeof(LOCKING_ANDX_RANGE), GFP_KERNEL);
@@ -2110,6 +2119,7 @@ static int cifs_writepages(struct address_space *mapping,
        pgoff_t end, index;
        struct cifs_writedata *wdata;
        int rc = 0;
+       int saved_rc = 0;
        unsigned int xid;
 
        /*
@@ -2138,8 +2148,10 @@ retry:
 
                rc = server->ops->wait_mtu_credits(server, cifs_sb->wsize,
                                                   &wsize, &credits);
-               if (rc)
+               if (rc != 0) {
+                       done = true;
                        break;
+               }
 
                tofind = min((wsize / PAGE_SIZE) - 1, end - index) + 1;
 
@@ -2147,6 +2159,7 @@ retry:
                                                  &found_pages);
                if (!wdata) {
                        rc = -ENOMEM;
+                       done = true;
                        add_credits_and_wake_if(server, credits, 0);
                        break;
                }
@@ -2175,7 +2188,7 @@ retry:
                if (rc != 0) {
                        add_credits_and_wake_if(server, wdata->credits, 0);
                        for (i = 0; i < nr_pages; ++i) {
-                               if (rc == -EAGAIN)
+                               if (is_retryable_error(rc))
                                        redirty_page_for_writepage(wbc,
                                                           wdata->pages[i]);
                                else
@@ -2183,7 +2196,7 @@ retry:
                                end_page_writeback(wdata->pages[i]);
                                put_page(wdata->pages[i]);
                        }
-                       if (rc != -EAGAIN)
+                       if (!is_retryable_error(rc))
                                mapping_set_error(mapping, rc);
                }
                kref_put(&wdata->refcount, cifs_writedata_release);
@@ -2193,6 +2206,15 @@ retry:
                        continue;
                }
 
+               /* Return immediately if we received a signal during writing */
+               if (is_interrupt_error(rc)) {
+                       done = true;
+                       break;
+               }
+
+               if (rc != 0 && saved_rc == 0)
+                       saved_rc = rc;
+
                wbc->nr_to_write -= nr_pages;
                if (wbc->nr_to_write <= 0)
                        done = true;
@@ -2210,6 +2232,9 @@ retry:
                goto retry;
        }
 
+       if (saved_rc != 0)
+               rc = saved_rc;
+
        if (wbc->range_cyclic || (range_whole && wbc->nr_to_write > 0))
                mapping->writeback_index = index;
 
@@ -2242,8 +2267,8 @@ cifs_writepage_locked(struct page *page, struct writeback_control *wbc)
        set_page_writeback(page);
 retry_write:
        rc = cifs_partialpagewrite(page, 0, PAGE_SIZE);
-       if (rc == -EAGAIN) {
-               if (wbc->sync_mode == WB_SYNC_ALL)
+       if (is_retryable_error(rc)) {
+               if (wbc->sync_mode == WB_SYNC_ALL && rc == -EAGAIN)
                        goto retry_write;
                redirty_page_for_writepage(wbc, page);
        } else if (rc != 0) {
@@ -2671,6 +2696,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
 
                        rc = cifs_write_allocate_pages(wdata->pages, nr_pages);
                        if (rc) {
+                               kvfree(wdata->pages);
                                kfree(wdata);
                                add_credits_and_wake_if(server, credits, 0);
                                break;
@@ -2682,6 +2708,7 @@ cifs_write_from_iter(loff_t offset, size_t len, struct iov_iter *from,
                        if (rc) {
                                for (i = 0; i < nr_pages; i++)
                                        put_page(wdata->pages[i]);
+                               kvfree(wdata->pages);
                                kfree(wdata);
                                add_credits_and_wake_if(server, credits, 0);
                                break;
@@ -3361,8 +3388,12 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
                        }
 
                        rc = cifs_read_allocate_pages(rdata, npages);
-                       if (rc)
-                               goto error;
+                       if (rc) {
+                               kvfree(rdata->pages);
+                               kfree(rdata);
+                               add_credits_and_wake_if(server, credits, 0);
+                               break;
+                       }
 
                        rdata->tailsz = PAGE_SIZE;
                }
@@ -3382,7 +3413,6 @@ cifs_send_async_read(loff_t offset, size_t len, struct cifsFileInfo *open_file,
                if (!rdata->cfile->invalidHandle ||
                    !(rc = cifs_reopen_file(rdata->cfile, true)))
                        rc = server->ops->async_readv(rdata);
-error:
                if (rc) {
                        add_credits_and_wake_if(server, rdata->credits, 0);
                        kref_put(&rdata->refcount,
index 13fb59a..4780036 100644 (file)
@@ -2257,6 +2257,11 @@ cifs_setattr_unix(struct dentry *direntry, struct iattr *attrs)
         * the flush returns error?
         */
        rc = filemap_write_and_wait(inode->i_mapping);
+       if (is_interrupt_error(rc)) {
+               rc = -ERESTARTSYS;
+               goto out;
+       }
+
        mapping_set_error(inode->i_mapping, rc);
        rc = 0;
 
@@ -2400,6 +2405,11 @@ cifs_setattr_nounix(struct dentry *direntry, struct iattr *attrs)
         * the flush returns error?
         */
        rc = filemap_write_and_wait(inode->i_mapping);
+       if (is_interrupt_error(rc)) {
+               rc = -ERESTARTSYS;
+               goto cifs_setattr_exit;
+       }
+
        mapping_set_error(inode->i_mapping, rc);
        rc = 0;
 
index 4ed10dd..b204e84 100644 (file)
@@ -122,12 +122,14 @@ smb2_unlock_range(struct cifsFileInfo *cfile, struct file_lock *flock,
 
        /*
         * Accessing maxBuf is racy with cifs_reconnect - need to store value
-        * and check it for zero before using.
+        * and check it before using.
         */
        max_buf = tcon->ses->server->maxBuf;
-       if (!max_buf)
+       if (max_buf < sizeof(struct smb2_lock_element))
                return -EINVAL;
 
+       BUILD_BUG_ON(sizeof(struct smb2_lock_element) > PAGE_SIZE);
+       max_buf = min_t(unsigned int, max_buf, PAGE_SIZE);
        max_num = max_buf / sizeof(struct smb2_lock_element);
        buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL);
        if (!buf)
@@ -264,6 +266,8 @@ smb2_push_mandatory_locks(struct cifsFileInfo *cfile)
                return -EINVAL;
        }
 
+       BUILD_BUG_ON(sizeof(struct smb2_lock_element) > PAGE_SIZE);
+       max_buf = min_t(unsigned int, max_buf, PAGE_SIZE);
        max_num = max_buf / sizeof(struct smb2_lock_element);
        buf = kcalloc(max_num, sizeof(struct smb2_lock_element), GFP_KERNEL);
        if (!buf) {
index f14533d..01a76bc 100644 (file)
@@ -293,6 +293,8 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
        int rc;
        struct smb2_file_all_info *smb2_data;
        __u32 create_options = 0;
+       struct cifs_fid fid;
+       bool no_cached_open = tcon->nohandlecache;
 
        *adjust_tz = false;
        *symlink = false;
@@ -301,6 +303,21 @@ smb2_query_path_info(const unsigned int xid, struct cifs_tcon *tcon,
                            GFP_KERNEL);
        if (smb2_data == NULL)
                return -ENOMEM;
+
+       /* If it is a root and its handle is cached then use it */
+       if (!strlen(full_path) && !no_cached_open) {
+               rc = open_shroot(xid, tcon, &fid);
+               if (rc)
+                       goto out;
+               rc = SMB2_query_info(xid, tcon, fid.persistent_fid,
+                                    fid.volatile_fid, smb2_data);
+               close_shroot(&tcon->crfid);
+               if (rc)
+                       goto out;
+               move_smb2_info_to_cifs(data, smb2_data);
+               goto out;
+       }
+
        if (backup_cred(cifs_sb))
                create_options |= CREATE_OPEN_BACKUP_INTENT;
 
index 6a9c475..7b8b58f 100644 (file)
@@ -648,6 +648,13 @@ smb2_is_valid_oplock_break(char *buffer, struct TCP_Server_Info *server)
        if (rsp->sync_hdr.Command != SMB2_OPLOCK_BREAK)
                return false;
 
+       if (rsp->sync_hdr.CreditRequest) {
+               spin_lock(&server->req_lock);
+               server->credits += le16_to_cpu(rsp->sync_hdr.CreditRequest);
+               spin_unlock(&server->req_lock);
+               wake_up(&server->request_q);
+       }
+
        if (rsp->StructureSize !=
                                smb2_rsp_struct_sizes[SMB2_OPLOCK_BREAK_HE]) {
                if (le16_to_cpu(rsp->StructureSize) == 44)
index cf7eb89..6f96e22 100644 (file)
@@ -34,6 +34,7 @@
 #include "cifs_ioctl.h"
 #include "smbdirect.h"
 
+/* Change credits for different ops and return the total number of credits */
 static int
 change_conf(struct TCP_Server_Info *server)
 {
@@ -41,17 +42,15 @@ change_conf(struct TCP_Server_Info *server)
        server->oplock_credits = server->echo_credits = 0;
        switch (server->credits) {
        case 0:
-               return -1;
+               return 0;
        case 1:
                server->echoes = false;
                server->oplocks = false;
-               cifs_dbg(VFS, "disabling echoes and oplocks\n");
                break;
        case 2:
                server->echoes = true;
                server->oplocks = false;
                server->echo_credits = 1;
-               cifs_dbg(FYI, "disabling oplocks\n");
                break;
        default:
                server->echoes = true;
@@ -64,14 +63,15 @@ change_conf(struct TCP_Server_Info *server)
                server->echo_credits = 1;
        }
        server->credits -= server->echo_credits + server->oplock_credits;
-       return 0;
+       return server->credits + server->echo_credits + server->oplock_credits;
 }
 
 static void
 smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
                 const int optype)
 {
-       int *val, rc = 0;
+       int *val, rc = -1;
+
        spin_lock(&server->req_lock);
        val = server->ops->get_credits_field(server, optype);
 
@@ -101,8 +101,26 @@ smb2_add_credits(struct TCP_Server_Info *server, const unsigned int add,
        }
        spin_unlock(&server->req_lock);
        wake_up(&server->request_q);
-       if (rc)
-               cifs_reconnect(server);
+
+       if (server->tcpStatus == CifsNeedReconnect)
+               return;
+
+       switch (rc) {
+       case -1:
+               /* change_conf hasn't been executed */
+               break;
+       case 0:
+               cifs_dbg(VFS, "Possible client or server bug - zero credits\n");
+               break;
+       case 1:
+               cifs_dbg(VFS, "disabling echoes and oplocks\n");
+               break;
+       case 2:
+               cifs_dbg(FYI, "disabling oplocks\n");
+               break;
+       default:
+               cifs_dbg(FYI, "add %u credits total=%d\n", add, rc);
+       }
 }
 
 static void
@@ -136,7 +154,11 @@ smb2_get_credits(struct mid_q_entry *mid)
 {
        struct smb2_sync_hdr *shdr = (struct smb2_sync_hdr *)mid->resp_buf;
 
-       return le16_to_cpu(shdr->CreditRequest);
+       if (mid->mid_state == MID_RESPONSE_RECEIVED
+           || mid->mid_state == MID_RESPONSE_MALFORMED)
+               return le16_to_cpu(shdr->CreditRequest);
+
+       return 0;
 }
 
 static int
@@ -165,14 +187,14 @@ smb2_wait_mtu_credits(struct TCP_Server_Info *server, unsigned int size,
 
                        scredits = server->credits;
                        /* can deadlock with reopen */
-                       if (scredits == 1) {
+                       if (scredits <= 8) {
                                *num = SMB2_MAX_BUFFER_SIZE;
                                *credits = 0;
                                break;
                        }
 
-                       /* leave one credit for a possible reopen */
-                       scredits--;
+                       /* leave some credits for reopen and other ops */
+                       scredits -= 8;
                        *num = min_t(unsigned int, size,
                                     scredits * SMB2_MAX_BUFFER_SIZE);
 
@@ -844,7 +866,9 @@ smb2_query_eas(const unsigned int xid, struct cifs_tcon *tcon,
                                      FILE_READ_EA,
                                      FILE_FULL_EA_INFORMATION,
                                      SMB2_O_INFO_FILE,
-                                     SMB2_MAX_EA_BUF,
+                                     CIFSMaxBufSize -
+                                     MAX_SMB2_CREATE_RESPONSE_SIZE -
+                                     MAX_SMB2_CLOSE_RESPONSE_SIZE,
                                      &rsp_iov, &buftype, cifs_sb);
        if (rc) {
                /*
@@ -3189,11 +3213,23 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
                        server->ops->is_status_pending(buf, server, 0))
                return -1;
 
-       rdata->result = server->ops->map_error(buf, false);
+       /* set up first two iov to get credits */
+       rdata->iov[0].iov_base = buf;
+       rdata->iov[0].iov_len = 4;
+       rdata->iov[1].iov_base = buf + 4;
+       rdata->iov[1].iov_len =
+               min_t(unsigned int, buf_len, server->vals->read_rsp_size) - 4;
+       cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
+                rdata->iov[0].iov_base, rdata->iov[0].iov_len);
+       cifs_dbg(FYI, "1: iov_base=%p iov_len=%zu\n",
+                rdata->iov[1].iov_base, rdata->iov[1].iov_len);
+
+       rdata->result = server->ops->map_error(buf, true);
        if (rdata->result != 0) {
                cifs_dbg(FYI, "%s: server returned error %d\n",
                         __func__, rdata->result);
-               dequeue_mid(mid, rdata->result);
+               /* normal error on read response */
+               dequeue_mid(mid, false);
                return 0;
        }
 
@@ -3266,14 +3302,6 @@ handle_read_data(struct TCP_Server_Info *server, struct mid_q_entry *mid,
                return 0;
        }
 
-       /* set up first iov for signature check */
-       rdata->iov[0].iov_base = buf;
-       rdata->iov[0].iov_len = 4;
-       rdata->iov[1].iov_base = buf + 4;
-       rdata->iov[1].iov_len = server->vals->read_rsp_size - 4;
-       cifs_dbg(FYI, "0: iov_base=%p iov_len=%zu\n",
-                rdata->iov[0].iov_base, server->vals->read_rsp_size);
-
        length = rdata->copy_into_pages(server, rdata, &iter);
 
        kfree(bvec);
index e57f6aa..77b3aaa 100644 (file)
@@ -162,24 +162,31 @@ static int __smb2_reconnect(const struct nls_table *nlsc,
        int rc;
        struct dfs_cache_tgt_list tl;
        struct dfs_cache_tgt_iterator *it = NULL;
-       char tree[MAX_TREE_SIZE + 1];
+       char *tree;
        const char *tcp_host;
        size_t tcp_host_len;
        const char *dfs_host;
        size_t dfs_host_len;
 
+       tree = kzalloc(MAX_TREE_SIZE, GFP_KERNEL);
+       if (!tree)
+               return -ENOMEM;
+
        if (tcon->ipc) {
-               snprintf(tree, sizeof(tree), "\\\\%s\\IPC$",
+               snprintf(tree, MAX_TREE_SIZE, "\\\\%s\\IPC$",
                         tcon->ses->server->hostname);
-               return SMB2_tcon(0, tcon->ses, tree, tcon, nlsc);
+               rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc);
+               goto out;
        }
 
-       if (!tcon->dfs_path)
-               return SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nlsc);
+       if (!tcon->dfs_path) {
+               rc = SMB2_tcon(0, tcon->ses, tcon->treeName, tcon, nlsc);
+               goto out;
+       }
 
        rc = dfs_cache_noreq_find(tcon->dfs_path + 1, NULL, &tl);
        if (rc)
-               return rc;
+               goto out;
 
        extract_unc_hostname(tcon->ses->server->hostname, &tcp_host,
                             &tcp_host_len);
@@ -199,7 +206,7 @@ static int __smb2_reconnect(const struct nls_table *nlsc,
                        continue;
                }
 
-               snprintf(tree, sizeof(tree), "\\%s", tgt);
+               snprintf(tree, MAX_TREE_SIZE, "\\%s", tgt);
 
                rc = SMB2_tcon(0, tcon->ses, tree, tcon, nlsc);
                if (!rc)
@@ -216,6 +223,8 @@ static int __smb2_reconnect(const struct nls_table *nlsc,
                        rc = -ENOENT;
        }
        dfs_cache_free_tgts(&tl);
+out:
+       kfree(tree);
        return rc;
 }
 #else
@@ -2807,6 +2816,7 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
        int resp_buftype = CIFS_NO_BUFFER;
        struct cifs_ses *ses = tcon->ses;
        int flags = 0;
+       bool allocated = false;
 
        cifs_dbg(FYI, "Query Info\n");
 
@@ -2846,14 +2856,21 @@ query_info(const unsigned int xid, struct cifs_tcon *tcon,
                                        "Error %d allocating memory for acl\n",
                                        rc);
                                *dlen = 0;
+                               rc = -ENOMEM;
                                goto qinf_exit;
                        }
+                       allocated = true;
                }
        }
 
        rc = smb2_validate_and_copy_iov(le16_to_cpu(rsp->OutputBufferOffset),
                                        le32_to_cpu(rsp->OutputBufferLength),
                                        &rsp_iov, min_len, *data);
+       if (rc && allocated) {
+               kfree(*data);
+               *data = NULL;
+               *dlen = 0;
+       }
 
 qinf_exit:
        SMB2_query_info_free(&rqst);
@@ -2907,9 +2924,10 @@ smb2_echo_callback(struct mid_q_entry *mid)
 {
        struct TCP_Server_Info *server = mid->callback_data;
        struct smb2_echo_rsp *rsp = (struct smb2_echo_rsp *)mid->resp_buf;
-       unsigned int credits_received = 1;
+       unsigned int credits_received = 0;
 
-       if (mid->mid_state == MID_RESPONSE_RECEIVED)
+       if (mid->mid_state == MID_RESPONSE_RECEIVED
+           || mid->mid_state == MID_RESPONSE_MALFORMED)
                credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
 
        DeleteMidQEntry(mid);
@@ -3166,7 +3184,7 @@ smb2_readv_callback(struct mid_q_entry *mid)
        struct TCP_Server_Info *server = tcon->ses->server;
        struct smb2_sync_hdr *shdr =
                                (struct smb2_sync_hdr *)rdata->iov[0].iov_base;
-       unsigned int credits_received = 1;
+       unsigned int credits_received = 0;
        struct smb_rqst rqst = { .rq_iov = rdata->iov,
                                 .rq_nvec = 2,
                                 .rq_pages = rdata->pages,
@@ -3205,6 +3223,9 @@ smb2_readv_callback(struct mid_q_entry *mid)
                task_io_account_read(rdata->got_bytes);
                cifs_stats_bytes_read(tcon, rdata->got_bytes);
                break;
+       case MID_RESPONSE_MALFORMED:
+               credits_received = le16_to_cpu(shdr->CreditRequest);
+               /* fall through */
        default:
                if (rdata->result != -ENODATA)
                        rdata->result = -EIO;
@@ -3220,8 +3241,17 @@ smb2_readv_callback(struct mid_q_entry *mid)
                rdata->mr = NULL;
        }
 #endif
-       if (rdata->result)
+       if (rdata->result && rdata->result != -ENODATA) {
                cifs_stats_fail_inc(tcon, SMB2_READ_HE);
+               trace_smb3_read_err(0 /* xid */,
+                                   rdata->cfile->fid.persistent_fid,
+                                   tcon->tid, tcon->ses->Suid, rdata->offset,
+                                   rdata->bytes, rdata->result);
+       } else
+               trace_smb3_read_done(0 /* xid */,
+                                    rdata->cfile->fid.persistent_fid,
+                                    tcon->tid, tcon->ses->Suid,
+                                    rdata->offset, rdata->got_bytes);
 
        queue_work(cifsiod_wq, &rdata->work);
        DeleteMidQEntry(mid);
@@ -3278,12 +3308,14 @@ smb2_async_readv(struct cifs_readdata *rdata)
        if (rdata->credits) {
                shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(rdata->bytes,
                                                SMB2_MAX_BUFFER_SIZE));
-               shdr->CreditRequest = shdr->CreditCharge;
+               shdr->CreditRequest =
+                       cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 1);
                spin_lock(&server->req_lock);
                server->credits += rdata->credits -
                                                le16_to_cpu(shdr->CreditCharge);
                spin_unlock(&server->req_lock);
                wake_up(&server->request_q);
+               rdata->credits = le16_to_cpu(shdr->CreditCharge);
                flags |= CIFS_HAS_CREDITS;
        }
 
@@ -3294,13 +3326,11 @@ smb2_async_readv(struct cifs_readdata *rdata)
        if (rc) {
                kref_put(&rdata->refcount, cifs_readdata_release);
                cifs_stats_fail_inc(io_parms.tcon, SMB2_READ_HE);
-               trace_smb3_read_err(rc, 0 /* xid */, io_parms.persistent_fid,
-                                  io_parms.tcon->tid, io_parms.tcon->ses->Suid,
-                                  io_parms.offset, io_parms.length);
-       } else
-               trace_smb3_read_done(0 /* xid */, io_parms.persistent_fid,
-                                  io_parms.tcon->tid, io_parms.tcon->ses->Suid,
-                                  io_parms.offset, io_parms.length);
+               trace_smb3_read_err(0 /* xid */, io_parms.persistent_fid,
+                                   io_parms.tcon->tid,
+                                   io_parms.tcon->ses->Suid,
+                                   io_parms.offset, io_parms.length, rc);
+       }
 
        cifs_small_buf_release(buf);
        return rc;
@@ -3344,10 +3374,11 @@ SMB2_read(const unsigned int xid, struct cifs_io_parms *io_parms,
                if (rc != -ENODATA) {
                        cifs_stats_fail_inc(io_parms->tcon, SMB2_READ_HE);
                        cifs_dbg(VFS, "Send error in read = %d\n", rc);
+                       trace_smb3_read_err(xid, req->PersistentFileId,
+                                           io_parms->tcon->tid, ses->Suid,
+                                           io_parms->offset, io_parms->length,
+                                           rc);
                }
-               trace_smb3_read_err(rc, xid, req->PersistentFileId,
-                                   io_parms->tcon->tid, ses->Suid,
-                                   io_parms->offset, io_parms->length);
                free_rsp_buf(resp_buftype, rsp_iov.iov_base);
                return rc == -ENODATA ? 0 : rc;
        } else
@@ -3388,7 +3419,7 @@ smb2_writev_callback(struct mid_q_entry *mid)
        struct cifs_tcon *tcon = tlink_tcon(wdata->cfile->tlink);
        unsigned int written;
        struct smb2_write_rsp *rsp = (struct smb2_write_rsp *)mid->resp_buf;
-       unsigned int credits_received = 1;
+       unsigned int credits_received = 0;
 
        switch (mid->mid_state) {
        case MID_RESPONSE_RECEIVED:
@@ -3416,6 +3447,9 @@ smb2_writev_callback(struct mid_q_entry *mid)
        case MID_RETRY_NEEDED:
                wdata->result = -EAGAIN;
                break;
+       case MID_RESPONSE_MALFORMED:
+               credits_received = le16_to_cpu(rsp->sync_hdr.CreditRequest);
+               /* fall through */
        default:
                wdata->result = -EIO;
                break;
@@ -3433,8 +3467,17 @@ smb2_writev_callback(struct mid_q_entry *mid)
                wdata->mr = NULL;
        }
 #endif
-       if (wdata->result)
+       if (wdata->result) {
                cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
+               trace_smb3_write_err(0 /* no xid */,
+                                    wdata->cfile->fid.persistent_fid,
+                                    tcon->tid, tcon->ses->Suid, wdata->offset,
+                                    wdata->bytes, wdata->result);
+       } else
+               trace_smb3_write_done(0 /* no xid */,
+                                     wdata->cfile->fid.persistent_fid,
+                                     tcon->tid, tcon->ses->Suid,
+                                     wdata->offset, wdata->bytes);
 
        queue_work(cifsiod_wq, &wdata->work);
        DeleteMidQEntry(mid);
@@ -3555,12 +3598,14 @@ smb2_async_writev(struct cifs_writedata *wdata,
        if (wdata->credits) {
                shdr->CreditCharge = cpu_to_le16(DIV_ROUND_UP(wdata->bytes,
                                                    SMB2_MAX_BUFFER_SIZE));
-               shdr->CreditRequest = shdr->CreditCharge;
+               shdr->CreditRequest =
+                       cpu_to_le16(le16_to_cpu(shdr->CreditCharge) + 1);
                spin_lock(&server->req_lock);
                server->credits += wdata->credits -
                                                le16_to_cpu(shdr->CreditCharge);
                spin_unlock(&server->req_lock);
                wake_up(&server->request_q);
+               wdata->credits = le16_to_cpu(shdr->CreditCharge);
                flags |= CIFS_HAS_CREDITS;
        }
 
@@ -3574,10 +3619,7 @@ smb2_async_writev(struct cifs_writedata *wdata,
                                     wdata->bytes, rc);
                kref_put(&wdata->refcount, release);
                cifs_stats_fail_inc(tcon, SMB2_WRITE_HE);
-       } else
-               trace_smb3_write_done(0 /* no xid */, req->PersistentFileId,
-                                    tcon->tid, tcon->ses->Suid, wdata->offset,
-                                    wdata->bytes);
+       }
 
 async_writev_out:
        cifs_small_buf_release(req);
@@ -3803,8 +3845,8 @@ SMB2_query_directory(const unsigned int xid, struct cifs_tcon *tcon,
                    rsp->sync_hdr.Status == STATUS_NO_MORE_FILES) {
                        srch_inf->endOfSearch = true;
                        rc = 0;
-               }
-               cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
+               } else
+                       cifs_stats_fail_inc(tcon, SMB2_QUERY_DIRECTORY_HE);
                goto qdir_exit;
        }
 
@@ -4399,8 +4441,8 @@ SMB2_lease_break(const unsigned int xid, struct cifs_tcon *tcon,
        rc = cifs_send_recv(xid, ses, &rqst, &resp_buf_type, flags, &rsp_iov);
        cifs_small_buf_release(req);
 
-       please_key_low = (__u64 *)req->LeaseKey;
-       please_key_high = (__u64 *)(req->LeaseKey+8);
+       please_key_low = (__u64 *)lease_key;
+       please_key_high = (__u64 *)(lease_key+8);
        if (rc) {
                cifs_stats_fail_inc(tcon, SMB2_OPLOCK_BREAK_HE);
                trace_smb3_lease_err(le32_to_cpu(lease_state), tcon->tid,
index 7a2d0a2..538e229 100644 (file)
@@ -84,8 +84,9 @@
 
 #define NUMBER_OF_SMB2_COMMANDS        0x0013
 
-/* 4 len + 52 transform hdr + 64 hdr + 56 create rsp */
-#define MAX_SMB2_HDR_SIZE 0x00b0
+/* 52 transform hdr + 64 hdr + 88 create rsp */
+#define SMB2_TRANSFORM_HEADER_SIZE 52
+#define MAX_SMB2_HDR_SIZE 204
 
 #define SMB2_PROTO_NUMBER cpu_to_le32(0x424d53fe)
 #define SMB2_TRANSFORM_PROTO_NUM cpu_to_le32(0x424d53fd)
@@ -648,6 +649,13 @@ struct smb2_create_req {
        __u8   Buffer[0];
 } __packed;
 
+/*
+ * Maximum size of a SMB2_CREATE response is 64 (smb2 header) +
+ * 88 (fixed part of create response) + 520 (path) + 150 (contexts) +
+ * 2 bytes of padding.
+ */
+#define MAX_SMB2_CREATE_RESPONSE_SIZE 824
+
 struct smb2_create_rsp {
        struct smb2_sync_hdr sync_hdr;
        __le16 StructureSize;   /* Must be 89 */
@@ -996,6 +1004,11 @@ struct smb2_close_req {
        __u64  VolatileFileId; /* opaque endianness */
 } __packed;
 
+/*
+ * Maximum size of a SMB2_CLOSE response is 64 (smb2 header) + 60 (data)
+ */
+#define MAX_SMB2_CLOSE_RESPONSE_SIZE 124
+
 struct smb2_close_rsp {
        struct smb2_sync_hdr sync_hdr;
        __le16 StructureSize; /* 60 */
@@ -1398,8 +1411,6 @@ struct smb2_file_link_info { /* encoding of request for level 11 */
        char   FileName[0];     /* Name to be assigned to new link */
 } __packed; /* level 11 Set */
 
-#define SMB2_MAX_EA_BUF 65536
-
 struct smb2_file_full_ea_info { /* encoding of response for level 15 */
        __le32 next_entry_offset;
        __u8   flags;
index bd4a546..4654837 100644 (file)
@@ -3,16 +3,6 @@
  *   Copyright (C) 2018, Microsoft Corporation.
  *
  *   Author(s): Steve French <stfrench@microsoft.com>
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
  */
 #define CREATE_TRACE_POINTS
 #include "trace.h"
index fb04980..59be482 100644 (file)
@@ -3,16 +3,6 @@
  *   Copyright (C) 2018, Microsoft Corporation.
  *
  *   Author(s): Steve French <stfrench@microsoft.com>
- *
- *   This program is free software;  you can redistribute it and/or modify
- *   it under the terms of the GNU General Public License as published by
- *   the Free Software Foundation; either version 2 of the License, or
- *   (at your option) any later version.
- *
- *   This program is distributed in the hope that it will be useful,
- *   but WITHOUT ANY WARRANTY;  without even the implied warranty of
- *   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See
- *   the GNU General Public License for more details.
  */
 #undef TRACE_SYSTEM
 #define TRACE_SYSTEM cifs
index 5be7302..53532bd 100644 (file)
@@ -387,7 +387,7 @@ smbd_done:
        if (rc < 0 && rc != -EINTR)
                cifs_dbg(VFS, "Error %d sending data on socket to server\n",
                         rc);
-       else
+       else if (rc > 0)
                rc = 0;
 
        return rc;
@@ -783,8 +783,25 @@ cifs_setup_request(struct cifs_ses *ses, struct smb_rqst *rqst)
 }
 
 static void
-cifs_noop_callback(struct mid_q_entry *mid)
+cifs_compound_callback(struct mid_q_entry *mid)
+{
+       struct TCP_Server_Info *server = mid->server;
+
+       add_credits(server, server->ops->get_credits(mid), mid->optype);
+}
+
+static void
+cifs_compound_last_callback(struct mid_q_entry *mid)
 {
+       cifs_compound_callback(mid);
+       cifs_wake_up_task(mid);
+}
+
+static void
+cifs_cancelled_callback(struct mid_q_entry *mid)
+{
+       cifs_compound_callback(mid);
+       DeleteMidQEntry(mid);
 }
 
 int
@@ -795,7 +812,8 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
        int i, j, rc = 0;
        int timeout, optype;
        struct mid_q_entry *midQ[MAX_COMPOUND];
-       unsigned int credits = 0;
+       bool cancelled_mid[MAX_COMPOUND] = {false};
+       unsigned int credits[MAX_COMPOUND] = {0};
        char *buf;
 
        timeout = flags & CIFS_TIMEOUT_MASK;
@@ -813,13 +831,31 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                return -ENOENT;
 
        /*
-        * Ensure that we do not send more than 50 overlapping requests
-        * to the same server. We may make this configurable later or
-        * use ses->maxReq.
+        * Ensure we obtain 1 credit per request in the compound chain.
+        * It can be optimized further by waiting for all the credits
+        * at once but this can wait long enough if we don't have enough
+        * credits due to some heavy operations in progress or the server
+        * not granting us much, so a fallback to the current approach is
+        * needed anyway.
         */
-       rc = wait_for_free_request(ses->server, timeout, optype);
-       if (rc)
-               return rc;
+       for (i = 0; i < num_rqst; i++) {
+               rc = wait_for_free_request(ses->server, timeout, optype);
+               if (rc) {
+                       /*
+                        * We haven't sent an SMB packet to the server yet but
+                        * we already obtained credits for i requests in the
+                        * compound chain - need to return those credits back
+                        * for future use. Note that we need to call add_credits
+                        * multiple times to match the way we obtained credits
+                        * in the first place and to account for in flight
+                        * requests correctly.
+                        */
+                       for (j = 0; j < i; j++)
+                               add_credits(ses->server, 1, optype);
+                       return rc;
+               }
+               credits[i] = 1;
+       }
 
        /*
         * Make sure that we sign in the same order that we send on this socket
@@ -835,18 +871,24 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
                        for (j = 0; j < i; j++)
                                cifs_delete_mid(midQ[j]);
                        mutex_unlock(&ses->server->srv_mutex);
+
                        /* Update # of requests on wire to server */
-                       add_credits(ses->server, 1, optype);
+                       for (j = 0; j < num_rqst; j++)
+                               add_credits(ses->server, credits[j], optype);
                        return PTR_ERR(midQ[i]);
                }
 
                midQ[i]->mid_state = MID_REQUEST_SUBMITTED;
+               midQ[i]->optype = optype;
                /*
-                * We don't invoke the callback compounds unless it is the last
-                * request.
+                * Invoke callback for every part of the compound chain
+                * to calculate credits properly. Wake up this thread only when
+                * the last element is received.
                 */
                if (i < num_rqst - 1)
-                       midQ[i]->callback = cifs_noop_callback;
+                       midQ[i]->callback = cifs_compound_callback;
+               else
+                       midQ[i]->callback = cifs_compound_last_callback;
        }
        cifs_in_send_inc(ses->server);
        rc = smb_send_rqst(ses->server, num_rqst, rqst, flags);
@@ -860,8 +902,20 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
 
        mutex_unlock(&ses->server->srv_mutex);
 
-       if (rc < 0)
+       if (rc < 0) {
+               /* Sending failed for some reason - return credits back */
+               for (i = 0; i < num_rqst; i++)
+                       add_credits(ses->server, credits[i], optype);
                goto out;
+       }
+
+       /*
+        * At this point the request is passed to the network stack - we assume
+        * that any credits taken from the server structure on the client have
+        * been spent and we can't return them back. Once we receive responses
+        * we will collect credits granted by the server in the mid callbacks
+        * and add those credits to the server structure.
+        */
 
        /*
         * Compounding is never used during session establish.
@@ -875,36 +929,34 @@ compound_send_recv(const unsigned int xid, struct cifs_ses *ses,
 
        for (i = 0; i < num_rqst; i++) {
                rc = wait_for_response(ses->server, midQ[i]);
-               if (rc != 0) {
+               if (rc != 0)
+                       break;
+       }
+       if (rc != 0) {
+               for (; i < num_rqst; i++) {
                        cifs_dbg(VFS, "Cancelling wait for mid %llu cmd: %d\n",
                                 midQ[i]->mid, le16_to_cpu(midQ[i]->command));
                        send_cancel(ses->server, &rqst[i], midQ[i]);
                        spin_lock(&GlobalMid_Lock);
                        if (midQ[i]->mid_state == MID_REQUEST_SUBMITTED) {
                                midQ[i]->mid_flags |= MID_WAIT_CANCELLED;
-                               midQ[i]->callback = DeleteMidQEntry;
-                               spin_unlock(&GlobalMid_Lock);
-                               add_credits(ses->server, 1, optype);
-                               return rc;
+                               midQ[i]->callback = cifs_cancelled_callback;
+                               cancelled_mid[i] = true;
+                               credits[i] = 0;
                        }
                        spin_unlock(&GlobalMid_Lock);
                }
        }
 
-       for (i = 0; i < num_rqst; i++)
-               if (midQ[i]->resp_buf)
-                       credits += ses->server->ops->get_credits(midQ[i]);
-       if (!credits)
-               credits = 1;
-
        for (i = 0; i < num_rqst; i++) {
                if (rc < 0)
                        goto out;
 
                rc = cifs_sync_mid_result(midQ[i], ses->server);
                if (rc != 0) {
-                       add_credits(ses->server, credits, optype);
-                       return rc;
+                       /* mark this mid as cancelled to not free it below */
+                       cancelled_mid[i] = true;
+                       goto out;
                }
 
                if (!midQ[i]->resp_buf ||
@@ -951,9 +1003,10 @@ out:
         * This is prevented above by using a noop callback that will not
         * wake this thread except for the very last PDU.
         */
-       for (i = 0; i < num_rqst; i++)
-               cifs_delete_mid(midQ[i]);
-       add_credits(ses->server, credits, optype);
+       for (i = 0; i < num_rqst; i++) {
+               if (!cancelled_mid[i])
+                       cifs_delete_mid(midQ[i]);
+       }
 
        return rc;
 }
index 2593153..aac41ad 100644 (file)
@@ -119,6 +119,7 @@ struct dentry_stat_t dentry_stat = {
 
 static DEFINE_PER_CPU(long, nr_dentry);
 static DEFINE_PER_CPU(long, nr_dentry_unused);
+static DEFINE_PER_CPU(long, nr_dentry_negative);
 
 #if defined(CONFIG_SYSCTL) && defined(CONFIG_PROC_FS)
 
@@ -152,11 +153,22 @@ static long get_nr_dentry_unused(void)
        return sum < 0 ? 0 : sum;
 }
 
+static long get_nr_dentry_negative(void)
+{
+       int i;
+       long sum = 0;
+
+       for_each_possible_cpu(i)
+               sum += per_cpu(nr_dentry_negative, i);
+       return sum < 0 ? 0 : sum;
+}
+
 int proc_nr_dentry(struct ctl_table *table, int write, void __user *buffer,
                   size_t *lenp, loff_t *ppos)
 {
        dentry_stat.nr_dentry = get_nr_dentry();
        dentry_stat.nr_unused = get_nr_dentry_unused();
+       dentry_stat.nr_negative = get_nr_dentry_negative();
        return proc_doulongvec_minmax(table, write, buffer, lenp, ppos);
 }
 #endif
@@ -317,6 +329,8 @@ static inline void __d_clear_type_and_inode(struct dentry *dentry)
        flags &= ~(DCACHE_ENTRY_TYPE | DCACHE_FALLTHRU);
        WRITE_ONCE(dentry->d_flags, flags);
        dentry->d_inode = NULL;
+       if (dentry->d_flags & DCACHE_LRU_LIST)
+               this_cpu_inc(nr_dentry_negative);
 }
 
 static void dentry_free(struct dentry *dentry)
@@ -371,6 +385,11 @@ static void dentry_unlink_inode(struct dentry * dentry)
  * The per-cpu "nr_dentry_unused" counters are updated with
  * the DCACHE_LRU_LIST bit.
  *
+ * The per-cpu "nr_dentry_negative" counters are only updated
+ * when deleted from or added to the per-superblock LRU list, not
+ * from/to the shrink list. That is to avoid an unneeded dec/inc
+ * pair when moving from LRU to shrink list in select_collect().
+ *
  * These helper functions make sure we always follow the
  * rules. d_lock must be held by the caller.
  */
@@ -380,6 +399,8 @@ static void d_lru_add(struct dentry *dentry)
        D_FLAG_VERIFY(dentry, 0);
        dentry->d_flags |= DCACHE_LRU_LIST;
        this_cpu_inc(nr_dentry_unused);
+       if (d_is_negative(dentry))
+               this_cpu_inc(nr_dentry_negative);
        WARN_ON_ONCE(!list_lru_add(&dentry->d_sb->s_dentry_lru, &dentry->d_lru));
 }
 
@@ -388,6 +409,8 @@ static void d_lru_del(struct dentry *dentry)
        D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
        dentry->d_flags &= ~DCACHE_LRU_LIST;
        this_cpu_dec(nr_dentry_unused);
+       if (d_is_negative(dentry))
+               this_cpu_dec(nr_dentry_negative);
        WARN_ON_ONCE(!list_lru_del(&dentry->d_sb->s_dentry_lru, &dentry->d_lru));
 }
 
@@ -418,6 +441,8 @@ static void d_lru_isolate(struct list_lru_one *lru, struct dentry *dentry)
        D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
        dentry->d_flags &= ~DCACHE_LRU_LIST;
        this_cpu_dec(nr_dentry_unused);
+       if (d_is_negative(dentry))
+               this_cpu_dec(nr_dentry_negative);
        list_lru_isolate(lru, &dentry->d_lru);
 }
 
@@ -426,6 +451,8 @@ static void d_lru_shrink_move(struct list_lru_one *lru, struct dentry *dentry,
 {
        D_FLAG_VERIFY(dentry, DCACHE_LRU_LIST);
        dentry->d_flags |= DCACHE_SHRINK_LIST;
+       if (d_is_negative(dentry))
+               this_cpu_dec(nr_dentry_negative);
        list_lru_isolate_move(lru, &dentry->d_lru, list);
 }
 
@@ -1188,15 +1215,11 @@ static enum lru_status dentry_lru_isolate_shrink(struct list_head *item,
  */
 void shrink_dcache_sb(struct super_block *sb)
 {
-       long freed;
-
        do {
                LIST_HEAD(dispose);
 
-               freed = list_lru_walk(&sb->s_dentry_lru,
+               list_lru_walk(&sb->s_dentry_lru,
                        dentry_lru_isolate_shrink, &dispose, 1024);
-
-               this_cpu_sub(nr_dentry_unused, freed);
                shrink_dentry_list(&dispose);
        } while (list_lru_count(&sb->s_dentry_lru) > 0);
 }
@@ -1820,6 +1843,11 @@ static void __d_instantiate(struct dentry *dentry, struct inode *inode)
        WARN_ON(d_in_lookup(dentry));
 
        spin_lock(&dentry->d_lock);
+       /*
+        * Decrement negative dentry count if it was in the LRU list.
+        */
+       if (dentry->d_flags & DCACHE_LRU_LIST)
+               this_cpu_dec(nr_dentry_negative);
        hlist_add_head(&dentry->d_u.d_alias, &inode->i_dentry);
        raw_write_seqcount_begin(&dentry->d_seq);
        __d_set_inode_and_type(dentry, inode, add_flags);
index 13b0135..29c68c5 100644 (file)
@@ -324,7 +324,7 @@ static struct dentry *failed_creating(struct dentry *dentry)
        inode_unlock(d_inode(dentry->d_parent));
        dput(dentry);
        simple_release_fs(&debugfs_mount, &debugfs_mount_count);
-       return NULL;
+       return ERR_PTR(-ENOMEM);
 }
 
 static struct dentry *end_creating(struct dentry *dentry)
@@ -347,7 +347,7 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
        dentry = start_creating(name, parent);
 
        if (IS_ERR(dentry))
-               return NULL;
+               return dentry;
 
        inode = debugfs_get_inode(dentry->d_sb);
        if (unlikely(!inode))
@@ -386,7 +386,8 @@ static struct dentry *__debugfs_create_file(const char *name, umode_t mode,
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file is
  * to be removed (no automatic cleanup happens if your module is unloaded,
- * you are responsible here.)  If an error occurs, %NULL will be returned.
+ * you are responsible here.)  If an error occurs, %ERR_PTR(-ERROR) will be
+ * returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
  * returned.
@@ -464,7 +465,8 @@ EXPORT_SYMBOL_GPL(debugfs_create_file_unsafe);
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file is
  * to be removed (no automatic cleanup happens if your module is unloaded,
- * you are responsible here.)  If an error occurs, %NULL will be returned.
+ * you are responsible here.)  If an error occurs, %ERR_PTR(-ERROR) will be
+ * returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
  * returned.
@@ -495,7 +497,8 @@ EXPORT_SYMBOL_GPL(debugfs_create_file_size);
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the file is
  * to be removed (no automatic cleanup happens if your module is unloaded,
- * you are responsible here.)  If an error occurs, %NULL will be returned.
+ * you are responsible here.)  If an error occurs, %ERR_PTR(-ERROR) will be
+ * returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
  * returned.
@@ -506,7 +509,7 @@ struct dentry *debugfs_create_dir(const char *name, struct dentry *parent)
        struct inode *inode;
 
        if (IS_ERR(dentry))
-               return NULL;
+               return dentry;
 
        inode = debugfs_get_inode(dentry->d_sb);
        if (unlikely(!inode))
@@ -545,7 +548,7 @@ struct dentry *debugfs_create_automount(const char *name,
        struct inode *inode;
 
        if (IS_ERR(dentry))
-               return NULL;
+               return dentry;
 
        inode = debugfs_get_inode(dentry->d_sb);
        if (unlikely(!inode))
@@ -581,8 +584,8 @@ EXPORT_SYMBOL(debugfs_create_automount);
  * This function will return a pointer to a dentry if it succeeds.  This
  * pointer must be passed to the debugfs_remove() function when the symbolic
  * link is to be removed (no automatic cleanup happens if your module is
- * unloaded, you are responsible here.)  If an error occurs, %NULL will be
- * returned.
+ * unloaded, you are responsible here.)  If an error occurs, %ERR_PTR(-ERROR)
+ * will be returned.
  *
  * If debugfs is not enabled in the kernel, the value -%ENODEV will be
  * returned.
@@ -594,12 +597,12 @@ struct dentry *debugfs_create_symlink(const char *name, struct dentry *parent,
        struct inode *inode;
        char *link = kstrdup(target, GFP_KERNEL);
        if (!link)
-               return NULL;
+               return ERR_PTR(-ENOMEM);
 
        dentry = start_creating(name, parent);
        if (IS_ERR(dentry)) {
                kfree(link);
-               return NULL;
+               return dentry;
        }
 
        inode = debugfs_get_inode(dentry->d_sb);
@@ -787,6 +790,13 @@ struct dentry *debugfs_rename(struct dentry *old_dir, struct dentry *old_dentry,
        struct dentry *dentry = NULL, *trap;
        struct name_snapshot old_name;
 
+       if (IS_ERR(old_dir))
+               return old_dir;
+       if (IS_ERR(new_dir))
+               return new_dir;
+       if (IS_ERR_OR_NULL(old_dentry))
+               return old_dentry;
+
        trap = lock_rename(new_dir, old_dir);
        /* Source or destination directories don't exist? */
        if (d_really_is_negative(old_dir) || d_really_is_negative(new_dir))
@@ -820,7 +830,9 @@ exit:
        if (dentry && !IS_ERR(dentry))
                dput(dentry);
        unlock_rename(new_dir, old_dir);
-       return NULL;
+       if (IS_ERR(dentry))
+               return dentry;
+       return ERR_PTR(-EINVAL);
 }
 EXPORT_SYMBOL_GPL(debugfs_rename);
 
index dbc1a1f..ec2fb6f 100644 (file)
@@ -679,6 +679,7 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio,
        unsigned long fs_count; /* Number of filesystem-sized blocks */
        int create;
        unsigned int i_blkbits = sdio->blkbits + sdio->blkfactor;
+       loff_t i_size;
 
        /*
         * If there was a memory error and we've overwritten all the
@@ -708,8 +709,8 @@ static int get_more_blocks(struct dio *dio, struct dio_submit *sdio,
                 */
                create = dio->op == REQ_OP_WRITE;
                if (dio->flags & DIO_SKIP_HOLES) {
-                       if (fs_startblk <= ((i_size_read(dio->inode) - 1) >>
-                                                       i_blkbits))
+                       i_size = i_size_read(dio->inode);
+                       if (i_size && fs_startblk <= (i_size - 1) >> i_blkbits)
                                create = 0;
                }
 
index 8237701..d31b6c7 100644 (file)
@@ -21,8 +21,13 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused)
        spin_lock(&sb->s_inode_list_lock);
        list_for_each_entry(inode, &sb->s_inodes, i_sb_list) {
                spin_lock(&inode->i_lock);
+               /*
+                * We must skip inodes in unusual state. We may also skip
+                * inodes without pages but we deliberately won't in case
+                * we need to reschedule to avoid softlockups.
+                */
                if ((inode->i_state & (I_FREEING|I_WILL_FREE|I_NEW)) ||
-                   (inode->i_mapping->nrpages == 0)) {
+                   (inode->i_mapping->nrpages == 0 && !need_resched())) {
                        spin_unlock(&inode->i_lock);
                        continue;
                }
@@ -30,6 +35,7 @@ static void drop_pagecache_sb(struct super_block *sb, void *unused)
                spin_unlock(&inode->i_lock);
                spin_unlock(&sb->s_inode_list_lock);
 
+               cond_resched();
                invalidate_mapping_pages(inode->i_mapping, 0, -1);
                iput(toput_inode);
                toput_inode = inode;
index 712f009..5508baa 100644 (file)
@@ -116,16 +116,8 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
                goto out;
        }
 
-       ret = file_write_and_wait_range(file, start, end);
-       if (ret)
-               return ret;
-
        if (!journal) {
-               struct writeback_control wbc = {
-                       .sync_mode = WB_SYNC_ALL
-               };
-
-               ret = ext4_write_inode(inode, &wbc);
+               ret = __generic_file_fsync(file, start, end, datasync);
                if (!ret)
                        ret = ext4_sync_parent(inode);
                if (test_opt(inode->i_sb, BARRIER))
@@ -133,6 +125,9 @@ int ext4_sync_file(struct file *file, loff_t start, loff_t end, int datasync)
                goto out;
        }
 
+       ret = file_write_and_wait_range(file, start, end);
+       if (ret)
+               return ret;
        /*
         * data=writeback,ordered:
         *  The caller's filemap_fdatawrite()/wait will sync the data.
index b40168f..36855c1 100644 (file)
@@ -331,11 +331,22 @@ struct inode_switch_wbs_context {
        struct work_struct      work;
 };
 
+static void bdi_down_write_wb_switch_rwsem(struct backing_dev_info *bdi)
+{
+       down_write(&bdi->wb_switch_rwsem);
+}
+
+static void bdi_up_write_wb_switch_rwsem(struct backing_dev_info *bdi)
+{
+       up_write(&bdi->wb_switch_rwsem);
+}
+
 static void inode_switch_wbs_work_fn(struct work_struct *work)
 {
        struct inode_switch_wbs_context *isw =
                container_of(work, struct inode_switch_wbs_context, work);
        struct inode *inode = isw->inode;
+       struct backing_dev_info *bdi = inode_to_bdi(inode);
        struct address_space *mapping = inode->i_mapping;
        struct bdi_writeback *old_wb = inode->i_wb;
        struct bdi_writeback *new_wb = isw->new_wb;
@@ -343,6 +354,12 @@ static void inode_switch_wbs_work_fn(struct work_struct *work)
        struct page *page;
        bool switched = false;
 
+       /*
+        * If @inode switches cgwb membership while sync_inodes_sb() is
+        * being issued, sync_inodes_sb() might miss it.  Synchronize.
+        */
+       down_read(&bdi->wb_switch_rwsem);
+
        /*
         * By the time control reaches here, RCU grace period has passed
         * since I_WB_SWITCH assertion and all wb stat update transactions
@@ -428,6 +445,8 @@ skip_switch:
        spin_unlock(&new_wb->list_lock);
        spin_unlock(&old_wb->list_lock);
 
+       up_read(&bdi->wb_switch_rwsem);
+
        if (switched) {
                wb_wakeup(new_wb);
                wb_put(old_wb);
@@ -468,9 +487,18 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
        if (inode->i_state & I_WB_SWITCH)
                return;
 
+       /*
+        * Avoid starting new switches while sync_inodes_sb() is in
+        * progress.  Otherwise, if the down_write protected issue path
+        * blocks heavily, we might end up starting a large number of
+        * switches which will block on the rwsem.
+        */
+       if (!down_read_trylock(&bdi->wb_switch_rwsem))
+               return;
+
        isw = kzalloc(sizeof(*isw), GFP_ATOMIC);
        if (!isw)
-               return;
+               goto out_unlock;
 
        /* find and pin the new wb */
        rcu_read_lock();
@@ -504,12 +532,14 @@ static void inode_switch_wbs(struct inode *inode, int new_wb_id)
         * Let's continue after I_WB_SWITCH is guaranteed to be visible.
         */
        call_rcu(&isw->rcu_head, inode_switch_wbs_rcu_fn);
-       return;
+       goto out_unlock;
 
 out_free:
        if (isw->new_wb)
                wb_put(isw->new_wb);
        kfree(isw);
+out_unlock:
+       up_read(&bdi->wb_switch_rwsem);
 }
 
 /**
@@ -887,6 +917,9 @@ fs_initcall(cgroup_writeback_init);
 
 #else  /* CONFIG_CGROUP_WRITEBACK */
 
+static void bdi_down_write_wb_switch_rwsem(struct backing_dev_info *bdi) { }
+static void bdi_up_write_wb_switch_rwsem(struct backing_dev_info *bdi) { }
+
 static struct bdi_writeback *
 locked_inode_to_wb_and_lock_list(struct inode *inode)
        __releases(&inode->i_lock)
@@ -2413,8 +2446,11 @@ void sync_inodes_sb(struct super_block *sb)
                return;
        WARN_ON(!rwsem_is_locked(&sb->s_umount));
 
+       /* protect against inode wb switch, see inode_switch_wbs_work_fn() */
+       bdi_down_write_wb_switch_rwsem(bdi);
        bdi_split_work_to_wbs(bdi, &work, false);
        wb_wait_for_completion(bdi, &done);
+       bdi_up_write_wb_switch_rwsem(bdi);
 
        wait_sb_inodes(sb);
 }
index a5e516a..809c0f2 100644 (file)
@@ -1742,7 +1742,6 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
        req->in.h.nodeid = outarg->nodeid;
        req->in.numargs = 2;
        req->in.argpages = 1;
-       req->page_descs[0].offset = offset;
        req->end = fuse_retrieve_end;
 
        index = outarg->offset >> PAGE_SHIFT;
@@ -1757,6 +1756,7 @@ static int fuse_retrieve(struct fuse_conn *fc, struct inode *inode,
 
                this_num = min_t(unsigned, num, PAGE_SIZE - offset);
                req->pages[req->num_pages] = page;
+               req->page_descs[req->num_pages].offset = offset;
                req->page_descs[req->num_pages].length = this_num;
                req->num_pages++;
 
@@ -2077,8 +2077,10 @@ static ssize_t fuse_dev_splice_write(struct pipe_inode_info *pipe,
 
        ret = fuse_dev_do_write(fud, &cs, len);
 
+       pipe_lock(pipe);
        for (idx = 0; idx < nbuf; idx++)
                pipe_buf_release(pipe, &bufs[idx]);
+       pipe_unlock(pipe);
 
 out:
        kvfree(bufs);
index ffaffe1..a59c16b 100644 (file)
@@ -1782,7 +1782,7 @@ static bool fuse_writepage_in_flight(struct fuse_req *new_req,
                spin_unlock(&fc->lock);
 
                dec_wb_stat(&bdi->wb, WB_WRITEBACK);
-               dec_node_page_state(page, NR_WRITEBACK_TEMP);
+               dec_node_page_state(new_req->pages[0], NR_WRITEBACK_TEMP);
                wb_writeout_inc(&bdi->wb);
                fuse_writepage_free(fc, new_req);
                fuse_request_free(new_req);
index 76baaa6..c2d4099 100644 (file)
@@ -628,6 +628,7 @@ void fuse_conn_init(struct fuse_conn *fc, struct user_namespace *user_ns)
        get_random_bytes(&fc->scramble_key, sizeof(fc->scramble_key));
        fc->pid_ns = get_pid_ns(task_active_pid_ns(current));
        fc->user_ns = get_user_ns(user_ns);
+       fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ;
 }
 EXPORT_SYMBOL_GPL(fuse_conn_init);
 
@@ -1162,7 +1163,6 @@ static int fuse_fill_super(struct super_block *sb, void *data, int silent)
        fc->user_id = d.user_id;
        fc->group_id = d.group_id;
        fc->max_read = max_t(unsigned, 4096, d.max_read);
-       fc->max_pages = FUSE_DEFAULT_MAX_PAGES_PER_REQ;
 
        /* Used by get_root_inode() */
        sb->s_fs_info = fc;
index f15b4c5..78510ab 100644 (file)
@@ -28,7 +28,6 @@
 #include "util.h"
 #include "trans.h"
 #include "dir.h"
-#include "lops.h"
 
 struct workqueue_struct *gfs2_freeze_wq;
 
index 5bfaf38..b8830fd 100644 (file)
@@ -733,7 +733,7 @@ void gfs2_write_log_header(struct gfs2_sbd *sdp, struct gfs2_jdesc *jd,
        lh->lh_crc = cpu_to_be32(crc);
 
        gfs2_log_write(sdp, page, sb->s_blocksize, 0, addr);
-       gfs2_log_submit_bio(&sdp->sd_log_bio, REQ_OP_WRITE | op_flags);
+       gfs2_log_submit_bio(&sdp->sd_log_bio, REQ_OP_WRITE, op_flags);
        log_flush_wait(sdp);
 }
 
@@ -810,7 +810,7 @@ void gfs2_log_flush(struct gfs2_sbd *sdp, struct gfs2_glock *gl, u32 flags)
 
        gfs2_ordered_write(sdp);
        lops_before_commit(sdp, tr);
-       gfs2_log_submit_bio(&sdp->sd_log_bio, REQ_OP_WRITE);
+       gfs2_log_submit_bio(&sdp->sd_log_bio, REQ_OP_WRITE, 0);
 
        if (sdp->sd_log_head != sdp->sd_log_flush_head) {
                log_flush_wait(sdp);
index 94dcab6..2295042 100644 (file)
@@ -17,9 +17,7 @@
 #include <linux/bio.h>
 #include <linux/fs.h>
 #include <linux/list_sort.h>
-#include <linux/blkdev.h>
 
-#include "bmap.h"
 #include "dir.h"
 #include "gfs2.h"
 #include "incore.h"
@@ -195,6 +193,7 @@ static void gfs2_end_log_write_bh(struct gfs2_sbd *sdp, struct bio_vec *bvec,
 /**
  * gfs2_end_log_write - end of i/o to the log
  * @bio: The bio
+ * @error: Status of i/o request
  *
  * Each bio_vec contains either data from the pagecache or data
  * relating to the log itself. Here we iterate over the bio_vec
@@ -231,19 +230,20 @@ static void gfs2_end_log_write(struct bio *bio)
 /**
  * gfs2_log_submit_bio - Submit any pending log bio
  * @biop: Address of the bio pointer
- * @opf: REQ_OP | op_flags
+ * @op: REQ_OP
+ * @op_flags: req_flag_bits
  *
  * Submit any pending part-built or full bio to the block device. If
  * there is no pending bio, then this is a no-op.
  */
 
-void gfs2_log_submit_bio(struct bio **biop, int opf)
+void gfs2_log_submit_bio(struct bio **biop, int op, int op_flags)
 {
        struct bio *bio = *biop;
        if (bio) {
                struct gfs2_sbd *sdp = bio->bi_private;
                atomic_inc(&sdp->sd_log_in_flight);
-               bio->bi_opf = opf;
+               bio_set_op_attrs(bio, op, op_flags);
                submit_bio(bio);
                *biop = NULL;
        }
@@ -304,7 +304,7 @@ static struct bio *gfs2_log_get_bio(struct gfs2_sbd *sdp, u64 blkno,
                nblk >>= sdp->sd_fsb2bb_shift;
                if (blkno == nblk && !flush)
                        return bio;
-               gfs2_log_submit_bio(biop, op);
+               gfs2_log_submit_bio(biop, op, 0);
        }
 
        *biop = gfs2_log_alloc_bio(sdp, blkno, end_io);
@@ -375,184 +375,6 @@ void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page)
                       gfs2_log_bmap(sdp));
 }
 
-/**
- * gfs2_end_log_read - end I/O callback for reads from the log
- * @bio: The bio
- *
- * Simply unlock the pages in the bio. The main thread will wait on them and
- * process them in order as necessary.
- */
-
-static void gfs2_end_log_read(struct bio *bio)
-{
-       struct page *page;
-       struct bio_vec *bvec;
-       int i;
-
-       bio_for_each_segment_all(bvec, bio, i) {
-               page = bvec->bv_page;
-               if (bio->bi_status) {
-                       int err = blk_status_to_errno(bio->bi_status);
-
-                       SetPageError(page);
-                       mapping_set_error(page->mapping, err);
-               }
-               unlock_page(page);
-       }
-
-       bio_put(bio);
-}
-
-/**
- * gfs2_jhead_pg_srch - Look for the journal head in a given page.
- * @jd: The journal descriptor
- * @page: The page to look in
- *
- * Returns: 1 if found, 0 otherwise.
- */
-
-static bool gfs2_jhead_pg_srch(struct gfs2_jdesc *jd,
-                             struct gfs2_log_header_host *head,
-                             struct page *page)
-{
-       struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
-       struct gfs2_log_header_host uninitialized_var(lh);
-       void *kaddr = kmap_atomic(page);
-       unsigned int offset;
-       bool ret = false;
-
-       for (offset = 0; offset < PAGE_SIZE; offset += sdp->sd_sb.sb_bsize) {
-               if (!__get_log_header(sdp, kaddr + offset, 0, &lh)) {
-                       if (lh.lh_sequence > head->lh_sequence)
-                               *head = lh;
-                       else {
-                               ret = true;
-                               break;
-                       }
-               }
-       }
-       kunmap_atomic(kaddr);
-       return ret;
-}
-
-/**
- * gfs2_jhead_process_page - Search/cleanup a page
- * @jd: The journal descriptor
- * @index: Index of the page to look into
- * @done: If set, perform only cleanup, else search and set if found.
- *
- * Find the page with 'index' in the journal's mapping. Search the page for
- * the journal head if requested (cleanup == false). Release refs on the
- * page so the page cache can reclaim it (put_page() twice). We grabbed a
- * reference on this page two times, first when we did a find_or_create_page()
- * to obtain the page to add it to the bio and second when we do a
- * find_get_page() here to get the page to wait on while I/O on it is being
- * completed.
- * This function is also used to free up a page we might've grabbed but not
- * used. Maybe we added it to a bio, but not submitted it for I/O. Or we
- * submitted the I/O, but we already found the jhead so we only need to drop
- * our references to the page.
- */
-
-static void gfs2_jhead_process_page(struct gfs2_jdesc *jd, unsigned long index,
-                                   struct gfs2_log_header_host *head,
-                                   bool *done)
-{
-       struct page *page;
-
-       page = find_get_page(jd->jd_inode->i_mapping, index);
-       wait_on_page_locked(page);
-
-       if (PageError(page))
-               *done = true;
-
-       if (!*done)
-               *done = gfs2_jhead_pg_srch(jd, head, page);
-
-       put_page(page); /* Once for find_get_page */
-       put_page(page); /* Once more for find_or_create_page */
-}
-
-/**
- * gfs2_find_jhead - find the head of a log
- * @jd: The journal descriptor
- * @head: The log descriptor for the head of the log is returned here
- *
- * Do a search of a journal by reading it in large chunks using bios and find
- * the valid log entry with the highest sequence number.  (i.e. the log head)
- *
- * Returns: 0 on success, errno otherwise
- */
-
-int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
-{
-       struct gfs2_sbd *sdp = GFS2_SB(jd->jd_inode);
-       struct address_space *mapping = jd->jd_inode->i_mapping;
-       struct gfs2_journal_extent *je;
-       u32 block, read_idx = 0, submit_idx = 0, index = 0;
-       int shift = PAGE_SHIFT - sdp->sd_sb.sb_bsize_shift;
-       int blocks_per_page = 1 << shift, sz, ret = 0;
-       struct bio *bio = NULL;
-       struct page *page;
-       bool done = false;
-       errseq_t since;
-
-       memset(head, 0, sizeof(*head));
-       if (list_empty(&jd->extent_list))
-               gfs2_map_journal_extents(sdp, jd);
-
-       since = filemap_sample_wb_err(mapping);
-       list_for_each_entry(je, &jd->extent_list, list) {
-               for (block = 0; block < je->blocks; block += blocks_per_page) {
-                       index = (je->lblock + block) >> shift;
-
-                       page = find_or_create_page(mapping, index, GFP_NOFS);
-                       if (!page) {
-                               ret = -ENOMEM;
-                               done = true;
-                               goto out;
-                       }
-
-                       if (bio) {
-                               sz = bio_add_page(bio, page, PAGE_SIZE, 0);
-                               if (sz == PAGE_SIZE)
-                                       goto page_added;
-                               submit_idx = index;
-                               submit_bio(bio);
-                               bio = NULL;
-                       }
-
-                       bio = gfs2_log_alloc_bio(sdp,
-                                                je->dblock + (index << shift),
-                                                gfs2_end_log_read);
-                       bio->bi_opf = REQ_OP_READ;
-                       sz = bio_add_page(bio, page, PAGE_SIZE, 0);
-                       gfs2_assert_warn(sdp, sz == PAGE_SIZE);
-
-page_added:
-                       if (submit_idx <= read_idx + BIO_MAX_PAGES) {
-                               /* Keep at least one bio in flight */
-                               continue;
-                       }
-
-                       gfs2_jhead_process_page(jd, read_idx++, head, &done);
-                       if (done)
-                               goto out;  /* found */
-               }
-       }
-
-out:
-       if (bio)
-               submit_bio(bio);
-       while (read_idx <= index)
-               gfs2_jhead_process_page(jd, read_idx++, head, &done);
-
-       if (!ret)
-               ret = filemap_check_wb_err(mapping, since);
-
-       return ret;
-}
-
 static struct page *gfs2_get_log_desc(struct gfs2_sbd *sdp, u32 ld_type,
                                      u32 ld_length, u32 ld_data1)
 {
index 331160f..711c4d8 100644 (file)
@@ -30,10 +30,8 @@ extern u64 gfs2_log_bmap(struct gfs2_sbd *sdp);
 extern void gfs2_log_write(struct gfs2_sbd *sdp, struct page *page,
                           unsigned size, unsigned offset, u64 blkno);
 extern void gfs2_log_write_page(struct gfs2_sbd *sdp, struct page *page);
-extern void gfs2_log_submit_bio(struct bio **biop, int opf);
+extern void gfs2_log_submit_bio(struct bio **biop, int op, int op_flags);
 extern void gfs2_pin(struct gfs2_sbd *sdp, struct buffer_head *bh);
-extern int gfs2_find_jhead(struct gfs2_jdesc *jd,
-                          struct gfs2_log_header_host *head);
 
 static inline unsigned int buf_limit(struct gfs2_sbd *sdp)
 {
index 1179763..b041cb8 100644 (file)
@@ -41,7 +41,6 @@
 #include "dir.h"
 #include "meta_io.h"
 #include "trace_gfs2.h"
-#include "lops.h"
 
 #define DO 0
 #define UNDO 1
index 7389e44..2dac430 100644 (file)
@@ -181,6 +181,129 @@ static int get_log_header(struct gfs2_jdesc *jd, unsigned int blk,
        return error;
 }
 
+/**
+ * find_good_lh - find a good log header
+ * @jd: the journal
+ * @blk: the segment to start searching from
+ * @lh: the log header to fill in
+ * @forward: if true search forward in the log, else search backward
+ *
+ * Call get_log_header() to get a log header for a segment, but if the
+ * segment is bad, either scan forward or backward until we find a good one.
+ *
+ * Returns: errno
+ */
+
+static int find_good_lh(struct gfs2_jdesc *jd, unsigned int *blk,
+                       struct gfs2_log_header_host *head)
+{
+       unsigned int orig_blk = *blk;
+       int error;
+
+       for (;;) {
+               error = get_log_header(jd, *blk, head);
+               if (error <= 0)
+                       return error;
+
+               if (++*blk == jd->jd_blocks)
+                       *blk = 0;
+
+               if (*blk == orig_blk) {
+                       gfs2_consist_inode(GFS2_I(jd->jd_inode));
+                       return -EIO;
+               }
+       }
+}
+
+/**
+ * jhead_scan - make sure we've found the head of the log
+ * @jd: the journal
+ * @head: this is filled in with the log descriptor of the head
+ *
+ * At this point, seg and lh should be either the head of the log or just
+ * before.  Scan forward until we find the head.
+ *
+ * Returns: errno
+ */
+
+static int jhead_scan(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
+{
+       unsigned int blk = head->lh_blkno;
+       struct gfs2_log_header_host lh;
+       int error;
+
+       for (;;) {
+               if (++blk == jd->jd_blocks)
+                       blk = 0;
+
+               error = get_log_header(jd, blk, &lh);
+               if (error < 0)
+                       return error;
+               if (error == 1)
+                       continue;
+
+               if (lh.lh_sequence == head->lh_sequence) {
+                       gfs2_consist_inode(GFS2_I(jd->jd_inode));
+                       return -EIO;
+               }
+               if (lh.lh_sequence < head->lh_sequence)
+                       break;
+
+               *head = lh;
+       }
+
+       return 0;
+}
+
+/**
+ * gfs2_find_jhead - find the head of a log
+ * @jd: the journal
+ * @head: the log descriptor for the head of the log is returned here
+ *
+ * Do a binary search of a journal and find the valid log entry with the
+ * highest sequence number.  (i.e. the log head)
+ *
+ * Returns: errno
+ */
+
+int gfs2_find_jhead(struct gfs2_jdesc *jd, struct gfs2_log_header_host *head)
+{
+       struct gfs2_log_header_host lh_1, lh_m;
+       u32 blk_1, blk_2, blk_m;
+       int error;
+
+       blk_1 = 0;
+       blk_2 = jd->jd_blocks - 1;
+
+       for (;;) {
+               blk_m = (blk_1 + blk_2) / 2;
+
+               error = find_good_lh(jd, &blk_1, &lh_1);
+               if (error)
+                       return error;
+
+               error = find_good_lh(jd, &blk_m, &lh_m);
+               if (error)
+                       return error;
+
+               if (blk_1 == blk_m || blk_m == blk_2)
+                       break;
+
+               if (lh_1.lh_sequence <= lh_m.lh_sequence)
+                       blk_1 = blk_m;
+               else
+                       blk_2 = blk_m;
+       }
+
+       error = jhead_scan(jd, &lh_1);
+       if (error)
+               return error;
+
+       *head = lh_1;
+
+       return error;
+}
+
 /**
  * foreach_descriptor - go through the active part of the log
  * @jd: the journal
index 99575ab..11d8124 100644 (file)
@@ -27,6 +27,8 @@ extern int gfs2_revoke_add(struct gfs2_jdesc *jd, u64 blkno, unsigned int where)
 extern int gfs2_revoke_check(struct gfs2_jdesc *jd, u64 blkno, unsigned int where);
 extern void gfs2_revoke_clean(struct gfs2_jdesc *jd);
 
+extern int gfs2_find_jhead(struct gfs2_jdesc *jd,
+                   struct gfs2_log_header_host *head);
 extern int gfs2_recover_journal(struct gfs2_jdesc *gfs2_jd, bool wait);
 extern void gfs2_recover_func(struct work_struct *work);
 extern int __get_log_header(struct gfs2_sbd *sdp,
index 831d7cb..17a8d3b 100644 (file)
@@ -1780,9 +1780,9 @@ static int gfs2_rbm_find(struct gfs2_rbm *rbm, u8 state, u32 *minext,
                        goto next_iter;
                }
                if (ret == -E2BIG) {
-                       n += rbm->bii - initial_bii;
                        rbm->bii = 0;
                        rbm->offset = 0;
+                       n += (rbm->bii - initial_bii);
                        goto res_covered_end_of_rgrp;
                }
                return ret;
index d4b11c9..ca71163 100644 (file)
@@ -45,7 +45,6 @@
 #include "util.h"
 #include "sys.h"
 #include "xattr.h"
-#include "lops.h"
 
 #define args_neq(a1, a2, x) ((a1)->ar_##x != (a2)->ar_##x)
 
index a2fcea5..32920a1 100644 (file)
@@ -383,16 +383,17 @@ hugetlb_vmdelete_list(struct rb_root_cached *root, pgoff_t start, pgoff_t end)
  * truncation is indicated by end of range being LLONG_MAX
  *     In this case, we first scan the range and release found pages.
  *     After releasing pages, hugetlb_unreserve_pages cleans up region/reserv
- *     maps and global counts.
+ *     maps and global counts.  Page faults can not race with truncation
+ *     in this routine.  hugetlb_no_page() prevents page faults in the
+ *     truncated range.  It checks i_size before allocation, and again after
+ *     with the page table lock for the page held.  The same lock must be
+ *     acquired to unmap a page.
  * hole punch is indicated if end is not LLONG_MAX
  *     In the hole punch case we scan the range and release found pages.
  *     Only when releasing a page is the associated region/reserv map
  *     deleted.  The region/reserv map for ranges without associated
- *     pages are not modified.
- *
- * Callers of this routine must hold the i_mmap_rwsem in write mode to prevent
- * races with page faults.
- *
+ *     pages are not modified.  Page faults can race with hole punch.
+ *     This is indicated if we find a mapped page.
  * Note: If the passed end of range value is beyond the end of file, but
  * not LLONG_MAX this routine still performs a hole punch operation.
  */
@@ -422,14 +423,32 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
 
                for (i = 0; i < pagevec_count(&pvec); ++i) {
                        struct page *page = pvec.pages[i];
+                       u32 hash;
 
                        index = page->index;
+                       hash = hugetlb_fault_mutex_hash(h, current->mm,
+                                                       &pseudo_vma,
+                                                       mapping, index, 0);
+                       mutex_lock(&hugetlb_fault_mutex_table[hash]);
+
                        /*
-                        * A mapped page is impossible as callers should unmap
-                        * all references before calling.  And, i_mmap_rwsem
-                        * prevents the creation of additional mappings.
+                        * If page is mapped, it was faulted in after being
+                        * unmapped in caller.  Unmap (again) now after taking
+                        * the fault mutex.  The mutex will prevent faults
+                        * until we finish removing the page.
+                        *
+                        * This race can only happen in the hole punch case.
+                        * Getting here in a truncate operation is a bug.
                         */
-                       VM_BUG_ON(page_mapped(page));
+                       if (unlikely(page_mapped(page))) {
+                               BUG_ON(truncate_op);
+
+                               i_mmap_lock_write(mapping);
+                               hugetlb_vmdelete_list(&mapping->i_mmap,
+                                       index * pages_per_huge_page(h),
+                                       (index + 1) * pages_per_huge_page(h));
+                               i_mmap_unlock_write(mapping);
+                       }
 
                        lock_page(page);
                        /*
@@ -451,6 +470,7 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
                        }
 
                        unlock_page(page);
+                       mutex_unlock(&hugetlb_fault_mutex_table[hash]);
                }
                huge_pagevec_release(&pvec);
                cond_resched();
@@ -462,20 +482,9 @@ static void remove_inode_hugepages(struct inode *inode, loff_t lstart,
 
 static void hugetlbfs_evict_inode(struct inode *inode)
 {
-       struct address_space *mapping = inode->i_mapping;
        struct resv_map *resv_map;
 
-       /*
-        * The vfs layer guarantees that there are no other users of this
-        * inode.  Therefore, it would be safe to call remove_inode_hugepages
-        * without holding i_mmap_rwsem.  We acquire and hold here to be
-        * consistent with other callers.  Since there will be no contention
-        * on the semaphore, overhead is negligible.
-        */
-       i_mmap_lock_write(mapping);
        remove_inode_hugepages(inode, 0, LLONG_MAX);
-       i_mmap_unlock_write(mapping);
-
        resv_map = (struct resv_map *)inode->i_mapping->private_data;
        /* root inode doesn't have the resv_map, so we should check it */
        if (resv_map)
@@ -496,8 +505,8 @@ static int hugetlb_vmtruncate(struct inode *inode, loff_t offset)
        i_mmap_lock_write(mapping);
        if (!RB_EMPTY_ROOT(&mapping->i_mmap.rb_root))
                hugetlb_vmdelete_list(&mapping->i_mmap, pgoff, 0);
-       remove_inode_hugepages(inode, offset, LLONG_MAX);
        i_mmap_unlock_write(mapping);
+       remove_inode_hugepages(inode, offset, LLONG_MAX);
        return 0;
 }
 
@@ -531,8 +540,8 @@ static long hugetlbfs_punch_hole(struct inode *inode, loff_t offset, loff_t len)
                        hugetlb_vmdelete_list(&mapping->i_mmap,
                                                hole_start >> PAGE_SHIFT,
                                                hole_end  >> PAGE_SHIFT);
-               remove_inode_hugepages(inode, hole_start, hole_end);
                i_mmap_unlock_write(mapping);
+               remove_inode_hugepages(inode, hole_start, hole_end);
                inode_unlock(inode);
        }
 
@@ -615,11 +624,7 @@ static long hugetlbfs_fallocate(struct file *file, int mode, loff_t offset,
                /* addr is the offset within the file (zero based) */
                addr = index * hpage_size;
 
-               /*
-                * fault mutex taken here, protects against fault path
-                * and hole punch.  inode_lock previously taken protects
-                * against truncation.
-                */
+               /* mutex taken here, fault path and hole punch */
                hash = hugetlb_fault_mutex_hash(h, mm, &pseudo_vma, mapping,
                                                index, addr);
                mutex_lock(&hugetlb_fault_mutex_table[hash]);
index 0cd47fe..73432e6 100644 (file)
@@ -730,11 +730,8 @@ static enum lru_status inode_lru_isolate(struct list_head *item,
                return LRU_REMOVED;
        }
 
-       /*
-        * Recently referenced inodes and inodes with many attached pages
-        * get one more pass.
-        */
-       if (inode->i_state & I_REFERENCED || inode->i_data.nrpages > 1) {
+       /* recently referenced inodes get one more pass */
+       if (inode->i_state & I_REFERENCED) {
                inode->i_state &= ~I_REFERENCED;
                spin_unlock(&inode->i_lock);
                return LRU_ROTATE;
index a3088fa..897c602 100644 (file)
@@ -116,6 +116,12 @@ iomap_page_create(struct inode *inode, struct page *page)
        atomic_set(&iop->read_count, 0);
        atomic_set(&iop->write_count, 0);
        bitmap_zero(iop->uptodate, PAGE_SIZE / SECTOR_SIZE);
+
+       /*
+        * migrate_page_move_mapping() assumes that pages with private data have
+        * their count elevated by 1.
+        */
+       get_page(page);
        set_page_private(page, (unsigned long)iop);
        SetPagePrivate(page);
        return iop;
@@ -132,6 +138,7 @@ iomap_page_release(struct page *page)
        WARN_ON_ONCE(atomic_read(&iop->write_count));
        ClearPagePrivate(page);
        set_page_private(page, 0);
+       put_page(page);
        kfree(iop);
 }
 
@@ -569,8 +576,10 @@ iomap_migrate_page(struct address_space *mapping, struct page *newpage,
 
        if (page_has_private(page)) {
                ClearPagePrivate(page);
+               get_page(newpage);
                set_page_private(newpage, page_private(page));
                set_page_private(page, 0);
+               put_page(page);
                SetPagePrivate(newpage);
        }
 
@@ -1804,6 +1813,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
        loff_t pos = iocb->ki_pos, start = pos;
        loff_t end = iocb->ki_pos + count - 1, ret = 0;
        unsigned int flags = IOMAP_DIRECT;
+       bool wait_for_completion = is_sync_kiocb(iocb);
        struct blk_plug plug;
        struct iomap_dio *dio;
 
@@ -1823,7 +1833,6 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
        dio->end_io = end_io;
        dio->error = 0;
        dio->flags = 0;
-       dio->wait_for_completion = is_sync_kiocb(iocb);
 
        dio->submit.iter = iter;
        dio->submit.waiter = current;
@@ -1878,7 +1887,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
                dio_warn_stale_pagecache(iocb->ki_filp);
        ret = 0;
 
-       if (iov_iter_rw(iter) == WRITE && !dio->wait_for_completion &&
+       if (iov_iter_rw(iter) == WRITE && !wait_for_completion &&
            !inode->i_sb->s_dio_done_wq) {
                ret = sb_init_dio_done_wq(inode->i_sb);
                if (ret < 0)
@@ -1894,7 +1903,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
                if (ret <= 0) {
                        /* magic error code to fall back to buffered I/O */
                        if (ret == -ENOTBLK) {
-                               dio->wait_for_completion = true;
+                               wait_for_completion = true;
                                ret = 0;
                        }
                        break;
@@ -1916,8 +1925,24 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
        if (dio->flags & IOMAP_DIO_WRITE_FUA)
                dio->flags &= ~IOMAP_DIO_NEED_SYNC;
 
+       /*
+        * We are about to drop our additional submission reference, which
+        * might be the last reference to the dio.  There are three three
+        * different ways we can progress here:
+        *
+        *  (a) If this is the last reference we will always complete and free
+        *      the dio ourselves.
+        *  (b) If this is not the last reference, and we serve an asynchronous
+        *      iocb, we must never touch the dio after the decrement, the
+        *      I/O completion handler will complete and free it.
+        *  (c) If this is not the last reference, but we serve a synchronous
+        *      iocb, the I/O completion handler will wake us up on the drop
+        *      of the final reference, and we will complete and free it here
+        *      after we got woken by the I/O completion handler.
+        */
+       dio->wait_for_completion = wait_for_completion;
        if (!atomic_dec_and_test(&dio->ref)) {
-               if (!dio->wait_for_completion)
+               if (!wait_for_completion)
                        return -EIOCBQUEUED;
 
                for (;;) {
@@ -1934,9 +1959,7 @@ iomap_dio_rw(struct kiocb *iocb, struct iov_iter *iter,
                __set_current_state(TASK_RUNNING);
        }
 
-       ret = iomap_dio_complete(dio);
-
-       return ret;
+       return iomap_dio_complete(dio);
 
 out_free_dio:
        kfree(dio);
index 46d691b..45b2322 100644 (file)
@@ -133,15 +133,9 @@ static ssize_t nfs4_copy_file_range(struct file *file_in, loff_t pos_in,
                                    struct file *file_out, loff_t pos_out,
                                    size_t count, unsigned int flags)
 {
-       ssize_t ret;
-
        if (file_inode(file_in) == file_inode(file_out))
                return -EINVAL;
-retry:
-       ret = nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
-       if (ret == -EAGAIN)
-               goto retry;
-       return ret;
+       return nfs42_proc_copy(file_in, pos_in, file_out, pos_out, count);
 }
 
 static loff_t nfs4_file_llseek(struct file *filep, loff_t offset, int whence)
index 3f23b68..bf34dda 100644 (file)
@@ -44,6 +44,7 @@
 #include <linux/keyctl.h>
 #include <linux/key-type.h>
 #include <keys/user-type.h>
+#include <keys/request_key_auth-type.h>
 #include <linux/module.h>
 
 #include "internal.h"
@@ -59,7 +60,7 @@ static struct key_type key_type_id_resolver_legacy;
 struct idmap_legacy_upcalldata {
        struct rpc_pipe_msg pipe_msg;
        struct idmap_msg idmap_msg;
-       struct key_construction *key_cons;
+       struct key      *authkey;
        struct idmap *idmap;
 };
 
@@ -384,7 +385,7 @@ static const match_table_t nfs_idmap_tokens = {
        { Opt_find_err, NULL }
 };
 
-static int nfs_idmap_legacy_upcall(struct key_construction *, const char *, void *);
+static int nfs_idmap_legacy_upcall(struct key *, void *);
 static ssize_t idmap_pipe_downcall(struct file *, const char __user *,
                                   size_t);
 static void idmap_release_pipe(struct inode *);
@@ -549,11 +550,12 @@ nfs_idmap_prepare_pipe_upcall(struct idmap *idmap,
 static void
 nfs_idmap_complete_pipe_upcall_locked(struct idmap *idmap, int ret)
 {
-       struct key_construction *cons = idmap->idmap_upcall_data->key_cons;
+       struct key *authkey = idmap->idmap_upcall_data->authkey;
 
        kfree(idmap->idmap_upcall_data);
        idmap->idmap_upcall_data = NULL;
-       complete_request_key(cons, ret);
+       complete_request_key(authkey, ret);
+       key_put(authkey);
 }
 
 static void
@@ -563,15 +565,14 @@ nfs_idmap_abort_pipe_upcall(struct idmap *idmap, int ret)
                nfs_idmap_complete_pipe_upcall_locked(idmap, ret);
 }
 
-static int nfs_idmap_legacy_upcall(struct key_construction *cons,
-                                  const char *op,
-                                  void *aux)
+static int nfs_idmap_legacy_upcall(struct key *authkey, void *aux)
 {
        struct idmap_legacy_upcalldata *data;
+       struct request_key_auth *rka = get_request_key_auth(authkey);
        struct rpc_pipe_msg *msg;
        struct idmap_msg *im;
        struct idmap *idmap = (struct idmap *)aux;
-       struct key *key = cons->key;
+       struct key *key = rka->target_key;
        int ret = -ENOKEY;
 
        if (!aux)
@@ -586,7 +587,7 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons,
        msg = &data->pipe_msg;
        im = &data->idmap_msg;
        data->idmap = idmap;
-       data->key_cons = cons;
+       data->authkey = key_get(authkey);
 
        ret = nfs_idmap_prepare_message(key->description, idmap, im, msg);
        if (ret < 0)
@@ -604,7 +605,7 @@ static int nfs_idmap_legacy_upcall(struct key_construction *cons,
 out2:
        kfree(data);
 out1:
-       complete_request_key(cons, ret);
+       complete_request_key(authkey, ret);
        return ret;
 }
 
@@ -651,9 +652,10 @@ out:
 static ssize_t
 idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
 {
+       struct request_key_auth *rka;
        struct rpc_inode *rpci = RPC_I(file_inode(filp));
        struct idmap *idmap = (struct idmap *)rpci->private;
-       struct key_construction *cons;
+       struct key *authkey;
        struct idmap_msg im;
        size_t namelen_in;
        int ret = -ENOKEY;
@@ -665,7 +667,8 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
        if (idmap->idmap_upcall_data == NULL)
                goto out_noupcall;
 
-       cons = idmap->idmap_upcall_data->key_cons;
+       authkey = idmap->idmap_upcall_data->authkey;
+       rka = get_request_key_auth(authkey);
 
        if (mlen != sizeof(im)) {
                ret = -ENOSPC;
@@ -690,9 +693,9 @@ idmap_pipe_downcall(struct file *filp, const char __user *src, size_t mlen)
 
        ret = nfs_idmap_read_and_verify_message(&im,
                        &idmap->idmap_upcall_data->idmap_msg,
-                       cons->key, cons->authkey);
+                       rka->target_key, authkey);
        if (ret >= 0) {
-               key_set_timeout(cons->key, nfs_idmap_cache_timeout);
+               key_set_timeout(rka->target_key, nfs_idmap_cache_timeout);
                ret = mlen;
        }
 
index 22ce3c8..0570391 100644 (file)
@@ -1895,6 +1895,11 @@ static int nfs_parse_devname(const char *dev_name,
        size_t len;
        char *end;
 
+       if (unlikely(!dev_name || !*dev_name)) {
+               dfprintk(MOUNT, "NFS: device name not specified\n");
+               return -EINVAL;
+       }
+
        /* Is the host name protected with square brakcets? */
        if (*dev_name == '[') {
                end = strchr(++dev_name, ']');
index 5a0bbf9..d09c9f8 100644 (file)
@@ -238,9 +238,9 @@ out:
 }
 
 /* A writeback failed: mark the page as bad, and invalidate the page cache */
-static void nfs_set_pageerror(struct page *page)
+static void nfs_set_pageerror(struct address_space *mapping)
 {
-       nfs_zap_mapping(page_file_mapping(page)->host, page_file_mapping(page));
+       nfs_zap_mapping(mapping->host, mapping);
 }
 
 /*
@@ -621,11 +621,12 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
        nfs_set_page_writeback(page);
        WARN_ON_ONCE(test_bit(PG_CLEAN, &req->wb_flags));
 
-       ret = 0;
+       ret = req->wb_context->error;
        /* If there is a fatal error that covers this write, just exit */
-       if (nfs_error_is_fatal_on_server(req->wb_context->error))
+       if (nfs_error_is_fatal_on_server(ret))
                goto out_launder;
 
+       ret = 0;
        if (!nfs_pageio_add_request(pgio, req)) {
                ret = pgio->pg_error;
                /*
@@ -635,9 +636,9 @@ static int nfs_page_async_flush(struct nfs_pageio_descriptor *pgio,
                        nfs_context_set_write_error(req->wb_context, ret);
                        if (nfs_error_is_fatal_on_server(ret))
                                goto out_launder;
-               }
+               } else
+                       ret = -EAGAIN;
                nfs_redirty_request(req);
-               ret = -EAGAIN;
        } else
                nfs_add_stats(page_file_mapping(page)->host,
                                NFSIOS_WRITEPAGES, 1);
@@ -993,7 +994,7 @@ static void nfs_write_completion(struct nfs_pgio_header *hdr)
                nfs_list_remove_request(req);
                if (test_bit(NFS_IOHDR_ERROR, &hdr->flags) &&
                    (hdr->good_bytes < bytes)) {
-                       nfs_set_pageerror(req->wb_page);
+                       nfs_set_pageerror(page_file_mapping(req->wb_page));
                        nfs_context_set_write_error(req->wb_context, hdr->error);
                        goto remove_req;
                }
@@ -1347,7 +1348,8 @@ int nfs_updatepage(struct file *file, struct page *page,
                unsigned int offset, unsigned int count)
 {
        struct nfs_open_context *ctx = nfs_file_open_context(file);
-       struct inode    *inode = page_file_mapping(page)->host;
+       struct address_space *mapping = page_file_mapping(page);
+       struct inode    *inode = mapping->host;
        int             status = 0;
 
        nfs_inc_stats(inode, NFSIOS_VFSUPDATEPAGE);
@@ -1365,7 +1367,7 @@ int nfs_updatepage(struct file *file, struct page *page,
 
        status = nfs_writepage_setup(ctx, page, offset, count);
        if (status < 0)
-               nfs_set_pageerror(page);
+               nfs_set_pageerror(mapping);
        else
                __set_page_dirty_nobuffers(page);
 out:
index b33f978..72a7681 100644 (file)
@@ -1239,8 +1239,8 @@ static __net_init int nfsd_init_net(struct net *net)
        retval = nfsd_idmap_init(net);
        if (retval)
                goto out_idmap_error;
-       nn->nfsd4_lease = 45;   /* default lease time */
-       nn->nfsd4_grace = 45;
+       nn->nfsd4_lease = 90;   /* default lease time */
+       nn->nfsd4_grace = 90;
        nn->somebody_reclaimed = false;
        nn->clverifier_counter = prandom_u32();
        nn->clientid_counter = prandom_u32();
index 9824e32..7dc98e1 100644 (file)
@@ -557,9 +557,11 @@ __be32 nfsd4_clone_file_range(struct file *src, u64 src_pos, struct file *dst,
        loff_t cloned;
 
        cloned = vfs_clone_file_range(src, src_pos, dst, dst_pos, count, 0);
+       if (cloned < 0)
+               return nfserrno(cloned);
        if (count && cloned != count)
-               cloned = -EINVAL;
-       return nfserrno(cloned < 0 ? cloned : 0);
+               return nfserrno(-EINVAL);
+       return 0;
 }
 
 ssize_t nfsd_copy_file_range(struct file *src, u64 src_pos, struct file *dst,
index 105576d..798f125 100644 (file)
@@ -724,8 +724,10 @@ SYSCALL_DEFINE3(inotify_add_watch, int, fd, const char __user *, pathname,
                return -EBADF;
 
        /* IN_MASK_ADD and IN_MASK_CREATE don't make sense together */
-       if (unlikely((mask & IN_MASK_ADD) && (mask & IN_MASK_CREATE)))
-               return -EINVAL;
+       if (unlikely((mask & IN_MASK_ADD) && (mask & IN_MASK_CREATE))) {
+               ret = -EINVAL;
+               goto fput_and_out;
+       }
 
        /* verify that this is indeed an inotify instance */
        if (unlikely(f.file->f_op != &inotify_fops)) {
index 633a634..f5ed951 100644 (file)
@@ -1086,10 +1086,6 @@ static int __set_oom_adj(struct file *file, int oom_adj, bool legacy)
 
                        task_lock(p);
                        if (!p->vfork_done && process_shares_mm(p, mm)) {
-                               pr_info("updating oom_score_adj for %d (%s) from %d to %d because it shares mm with %d (%s). Report if this is unexpected.\n",
-                                               task_pid_nr(p), p->comm,
-                                               p->signal->oom_score_adj, oom_adj,
-                                               task_pid_nr(task), task->comm);
                                p->signal->oom_score_adj = oom_adj;
                                if (!legacy && has_capability_noaudit(current, CAP_SYS_RESOURCE))
                                        p->signal->oom_score_adj_min = (short)oom_adj;
index 8ae1094..e39bac9 100644 (file)
@@ -256,7 +256,7 @@ struct dentry *proc_lookup_de(struct inode *dir, struct dentry *dentry,
                inode = proc_get_inode(dir->i_sb, de);
                if (!inode)
                        return ERR_PTR(-ENOMEM);
-               d_set_d_op(dentry, &proc_misc_dentry_ops);
+               d_set_d_op(dentry, de->proc_dops);
                return d_splice_alias(inode, dentry);
        }
        read_unlock(&proc_subdir_lock);
@@ -429,6 +429,8 @@ static struct proc_dir_entry *__proc_create(struct proc_dir_entry **parent,
        INIT_LIST_HEAD(&ent->pde_openers);
        proc_set_user(ent, (*parent)->uid, (*parent)->gid);
 
+       ent->proc_dops = &proc_misc_dentry_ops;
+
 out:
        return ent;
 }
index 5185d7f..95b1419 100644 (file)
@@ -44,6 +44,7 @@ struct proc_dir_entry {
        struct completion *pde_unload_completion;
        const struct inode_operations *proc_iops;
        const struct file_operations *proc_fops;
+       const struct dentry_operations *proc_dops;
        union {
                const struct seq_operations *seq_ops;
                int (*single_show)(struct seq_file *, void *);
index d5e0fcb..a7b1243 100644 (file)
@@ -38,6 +38,22 @@ static struct net *get_proc_net(const struct inode *inode)
        return maybe_get_net(PDE_NET(PDE(inode)));
 }
 
+static int proc_net_d_revalidate(struct dentry *dentry, unsigned int flags)
+{
+       return 0;
+}
+
+static const struct dentry_operations proc_net_dentry_ops = {
+       .d_revalidate   = proc_net_d_revalidate,
+       .d_delete       = always_delete_dentry,
+};
+
+static void pde_force_lookup(struct proc_dir_entry *pde)
+{
+       /* /proc/net/ entries can be changed under us by setns(CLONE_NEWNET) */
+       pde->proc_dops = &proc_net_dentry_ops;
+}
+
 static int seq_open_net(struct inode *inode, struct file *file)
 {
        unsigned int state_size = PDE(inode)->state_size;
@@ -90,6 +106,7 @@ struct proc_dir_entry *proc_create_net_data(const char *name, umode_t mode,
        p = proc_create_reg(name, mode, &parent, data);
        if (!p)
                return NULL;
+       pde_force_lookup(p);
        p->proc_fops = &proc_net_seq_fops;
        p->seq_ops = ops;
        p->state_size = state_size;
@@ -133,6 +150,7 @@ struct proc_dir_entry *proc_create_net_data_write(const char *name, umode_t mode
        p = proc_create_reg(name, mode, &parent, data);
        if (!p)
                return NULL;
+       pde_force_lookup(p);
        p->proc_fops = &proc_net_seq_fops;
        p->seq_ops = ops;
        p->state_size = state_size;
@@ -181,6 +199,7 @@ struct proc_dir_entry *proc_create_net_single(const char *name, umode_t mode,
        p = proc_create_reg(name, mode, &parent, data);
        if (!p)
                return NULL;
+       pde_force_lookup(p);
        p->proc_fops = &proc_net_single_fops;
        p->single_show = show;
        return proc_register(parent, p);
@@ -223,6 +242,7 @@ struct proc_dir_entry *proc_create_net_single_write(const char *name, umode_t mo
        p = proc_create_reg(name, mode, &parent, data);
        if (!p)
                return NULL;
+       pde_force_lookup(p);
        p->proc_fops = &proc_net_single_fops;
        p->single_show = show;
        p->write = write;
index f0ec9ed..85b0ef8 100644 (file)
@@ -423,7 +423,7 @@ struct mem_size_stats {
 };
 
 static void smaps_account(struct mem_size_stats *mss, struct page *page,
-               bool compound, bool young, bool dirty)
+               bool compound, bool young, bool dirty, bool locked)
 {
        int i, nr = compound ? 1 << compound_order(page) : 1;
        unsigned long size = nr * PAGE_SIZE;
@@ -450,24 +450,31 @@ static void smaps_account(struct mem_size_stats *mss, struct page *page,
                else
                        mss->private_clean += size;
                mss->pss += (u64)size << PSS_SHIFT;
+               if (locked)
+                       mss->pss_locked += (u64)size << PSS_SHIFT;
                return;
        }
 
        for (i = 0; i < nr; i++, page++) {
                int mapcount = page_mapcount(page);
+               unsigned long pss = (PAGE_SIZE << PSS_SHIFT);
 
                if (mapcount >= 2) {
                        if (dirty || PageDirty(page))
                                mss->shared_dirty += PAGE_SIZE;
                        else
                                mss->shared_clean += PAGE_SIZE;
-                       mss->pss += (PAGE_SIZE << PSS_SHIFT) / mapcount;
+                       mss->pss += pss / mapcount;
+                       if (locked)
+                               mss->pss_locked += pss / mapcount;
                } else {
                        if (dirty || PageDirty(page))
                                mss->private_dirty += PAGE_SIZE;
                        else
                                mss->private_clean += PAGE_SIZE;
-                       mss->pss += PAGE_SIZE << PSS_SHIFT;
+                       mss->pss += pss;
+                       if (locked)
+                               mss->pss_locked += pss;
                }
        }
 }
@@ -490,6 +497,7 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr,
 {
        struct mem_size_stats *mss = walk->private;
        struct vm_area_struct *vma = walk->vma;
+       bool locked = !!(vma->vm_flags & VM_LOCKED);
        struct page *page = NULL;
 
        if (pte_present(*pte)) {
@@ -532,7 +540,7 @@ static void smaps_pte_entry(pte_t *pte, unsigned long addr,
        if (!page)
                return;
 
-       smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte));
+       smaps_account(mss, page, false, pte_young(*pte), pte_dirty(*pte), locked);
 }
 
 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
@@ -541,6 +549,7 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr,
 {
        struct mem_size_stats *mss = walk->private;
        struct vm_area_struct *vma = walk->vma;
+       bool locked = !!(vma->vm_flags & VM_LOCKED);
        struct page *page;
 
        /* FOLL_DUMP will return -EFAULT on huge zero page */
@@ -555,7 +564,7 @@ static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr,
                /* pass */;
        else
                VM_BUG_ON_PAGE(1, page);
-       smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd));
+       smaps_account(mss, page, true, pmd_young(*pmd), pmd_dirty(*pmd), locked);
 }
 #else
 static void smaps_pmd_entry(pmd_t *pmd, unsigned long addr,
@@ -737,11 +746,8 @@ static void smap_gather_stats(struct vm_area_struct *vma,
                }
        }
 #endif
-
        /* mmap_sem is held in m_start */
        walk_page_vma(vma, &smaps_walk);
-       if (vma->vm_flags & VM_LOCKED)
-               mss->pss_locked += mss->pss;
 }
 
 #define SEQ_PUT_DEC(str, val) \
index 96f7d32..898c832 100644 (file)
@@ -128,7 +128,6 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], int id,
                     struct pstore_record *record)
 {
        struct persistent_ram_zone *prz;
-       bool update = (record->type == PSTORE_TYPE_DMESG);
 
        /* Give up if we never existed or have hit the end. */
        if (!przs)
@@ -139,7 +138,7 @@ ramoops_get_next_prz(struct persistent_ram_zone *przs[], int id,
                return NULL;
 
        /* Update old/shadowed buffer. */
-       if (update)
+       if (prz->type == PSTORE_TYPE_DMESG)
                persistent_ram_save_old(prz);
 
        if (!persistent_ram_old_size(prz))
@@ -711,18 +710,15 @@ static int ramoops_probe(struct platform_device *pdev)
 {
        struct device *dev = &pdev->dev;
        struct ramoops_platform_data *pdata = dev->platform_data;
+       struct ramoops_platform_data pdata_local;
        struct ramoops_context *cxt = &oops_cxt;
        size_t dump_mem_sz;
        phys_addr_t paddr;
        int err = -EINVAL;
 
        if (dev_of_node(dev) && !pdata) {
-               pdata = devm_kzalloc(&pdev->dev, sizeof(*pdata), GFP_KERNEL);
-               if (!pdata) {
-                       pr_err("cannot allocate platform data buffer\n");
-                       err = -ENOMEM;
-                       goto fail_out;
-               }
+               pdata = &pdata_local;
+               memset(pdata, 0, sizeof(*pdata));
 
                err = ramoops_parse_dt(pdev, pdata);
                if (err < 0)
index feeae80..aa85f28 100644 (file)
@@ -43,7 +43,8 @@ int sysfs_create_dir_ns(struct kobject *kobj, const void *ns)
        kuid_t uid;
        kgid_t gid;
 
-       BUG_ON(!kobj);
+       if (WARN_ON(!kobj))
+               return -EINVAL;
 
        if (kobj->parent)
                parent = kobj->parent->sd;
index bb71db6..5139845 100644 (file)
@@ -325,7 +325,8 @@ int sysfs_create_file_ns(struct kobject *kobj, const struct attribute *attr,
        kuid_t uid;
        kgid_t gid;
 
-       BUG_ON(!kobj || !kobj->sd || !attr);
+       if (WARN_ON(!kobj || !kobj->sd || !attr))
+               return -EINVAL;
 
        kobject_get_ownership(kobj, &uid, &gid);
        return sysfs_add_file_mode_ns(kobj->sd, attr, false, attr->mode,
@@ -537,7 +538,8 @@ int sysfs_create_bin_file(struct kobject *kobj,
        kuid_t uid;
        kgid_t gid;
 
-       BUG_ON(!kobj || !kobj->sd || !attr);
+       if (WARN_ON(!kobj || !kobj->sd || !attr))
+               return -EINVAL;
 
        kobject_get_ownership(kobj, &uid, &gid);
        return sysfs_add_file_mode_ns(kobj->sd, &attr->attr, true,
index 1eb2d63..5703860 100644 (file)
@@ -112,7 +112,8 @@ static int internal_create_group(struct kobject *kobj, int update,
        kgid_t gid;
        int error;
 
-       BUG_ON(!kobj || (!update && !kobj->sd));
+       if (WARN_ON(!kobj || (!update && !kobj->sd)))
+               return -EINVAL;
 
        /* Updates may happen before the object has been instantiated */
        if (unlikely(update && !kobj->sd))
index 215c225..c4deecc 100644 (file)
@@ -23,7 +23,8 @@ static int sysfs_do_create_link_sd(struct kernfs_node *parent,
 {
        struct kernfs_node *kn, *target = NULL;
 
-       BUG_ON(!name || !parent);
+       if (WARN_ON(!name || !parent))
+               return -EINVAL;
 
        /*
         * We don't own @target_kobj and it may be removed at any time.
index 1c8eecf..6acf1bf 100644 (file)
@@ -768,18 +768,23 @@ xrep_findroot_block(
                if (!uuid_equal(&btblock->bb_u.s.bb_uuid,
                                &mp->m_sb.sb_meta_uuid))
                        goto out;
+               /*
+                * Read verifiers can reference b_ops, so we set the pointer
+                * here.  If the verifier fails we'll reset the buffer state
+                * to what it was before we touched the buffer.
+                */
+               bp->b_ops = fab->buf_ops;
                fab->buf_ops->verify_read(bp);
                if (bp->b_error) {
+                       bp->b_ops = NULL;
                        bp->b_error = 0;
                        goto out;
                }
 
                /*
                 * Some read verifiers will (re)set b_ops, so we must be
-                * careful not to blow away any such assignment.
+                * careful not to change b_ops after running the verifier.
                 */
-               if (!bp->b_ops)
-                       bp->b_ops = fab->buf_ops;
        }
 
        /*
index 338b9d9..d9048bc 100644 (file)
@@ -449,6 +449,7 @@ xfs_map_blocks(
        }
 
        wpc->imap = imap;
+       xfs_trim_extent_eof(&wpc->imap, ip);
        trace_xfs_map_blocks_found(ip, offset, count, wpc->io_type, &imap);
        return 0;
 allocate_blocks:
@@ -459,6 +460,7 @@ allocate_blocks:
        ASSERT(whichfork == XFS_COW_FORK || cow_fsb == NULLFILEOFF ||
               imap.br_startoff + imap.br_blockcount <= cow_fsb);
        wpc->imap = imap;
+       xfs_trim_extent_eof(&wpc->imap, ip);
        trace_xfs_map_blocks_alloc(ip, offset, count, wpc->io_type, &imap);
        return 0;
 }
index eedc5e0..4f5f2ff 100644 (file)
@@ -776,10 +776,26 @@ _xfs_buf_read(
 }
 
 /*
+ * Set buffer ops on an unchecked buffer and validate it, if possible.
+ *
  * If the caller passed in an ops structure and the buffer doesn't have ops
  * assigned, set the ops and use them to verify the contents.  If the contents
  * cannot be verified, we'll clear XBF_DONE.  We assume the buffer has no
  * recorded errors and is already in XBF_DONE state.
+ *
+ * Under normal operations, every in-core buffer must have buffer ops assigned
+ * to them when the buffer is read in from disk so that we can validate the
+ * metadata.
+ *
+ * However, there are two scenarios where one can encounter in-core buffers
+ * that don't have buffer ops.  The first is during log recovery of buffers on
+ * a V4 filesystem, though these buffers are purged at the end of recovery.
+ *
+ * The other is online repair, which tries to match arbitrary metadata blocks
+ * with btree types in order to find the root.  If online repair doesn't match
+ * the buffer with /any/ btree type, the buffer remains in memory in DONE state
+ * with no ops, and a subsequent read_buf call from elsewhere will not set the
+ * ops.  This function helps us fix this situation.
  */
 int
 xfs_buf_ensure_ops(
@@ -1536,8 +1552,7 @@ __xfs_buf_submit(
                xfs_buf_ioerror(bp, -EIO);
                bp->b_flags &= ~XBF_DONE;
                xfs_buf_stale(bp);
-               if (bp->b_flags & XBF_ASYNC)
-                       xfs_buf_ioend(bp);
+               xfs_buf_ioend(bp);
                return -EIO;
        }
 
diff --git a/include/asm-generic/shmparam.h b/include/asm-generic/shmparam.h
new file mode 100644 (file)
index 0000000..8b78c0b
--- /dev/null
@@ -0,0 +1,7 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __ASM_GENERIC_SHMPARAM_H
+#define __ASM_GENERIC_SHMPARAM_H
+
+#define SHMLBA PAGE_SIZE        /* attach addr a multiple of this */
+
+#endif /* _ASM_GENERIC_SHMPARAM_H */
index 5736c94..2d4fc2d 100644 (file)
@@ -1365,6 +1365,13 @@ enum drm_dp_quirk {
         * to 16 bits. So will give a constant value (0x8000) for compatability.
         */
        DP_DPCD_QUIRK_CONSTANT_N,
+       /**
+        * @DP_DPCD_QUIRK_NO_PSR:
+        *
+        * The device does not support PSR even if reports that it supports or
+        * driver still need to implement proper handling for such device.
+        */
+       DP_DPCD_QUIRK_NO_PSR,
 };
 
 /**
index 59f005b..727af08 100644 (file)
@@ -616,7 +616,8 @@ void drm_dp_mst_dump_topology(struct seq_file *m,
                              struct drm_dp_mst_topology_mgr *mgr);
 
 void drm_dp_mst_topology_mgr_suspend(struct drm_dp_mst_topology_mgr *mgr);
-int drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr);
+int __must_check
+drm_dp_mst_topology_mgr_resume(struct drm_dp_mst_topology_mgr *mgr);
 struct drm_dp_mst_topology_state *drm_atomic_get_mst_topology_state(struct drm_atomic_state *state,
                                                                    struct drm_dp_mst_topology_mgr *mgr);
 int drm_dp_atomic_find_vcpi_slots(struct drm_atomic_state *state,
diff --git a/include/dt-bindings/clock/actions,s500-cmu.h b/include/dt-bindings/clock/actions,s500-cmu.h
new file mode 100644 (file)
index 0000000..030981c
--- /dev/null
@@ -0,0 +1,78 @@
+/* SPDX-License-Identifier: GPL-2.0+ */
+/*
+ * Device Tree binding constants for Actions Semi S500 Clock Management Unit
+ *
+ * Copyright (c) 2014 Actions Semi Inc.
+ * Copyright (c) 2018 LSI-TEC - Caninos Loucos
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_S500_CMU_H
+#define __DT_BINDINGS_CLOCK_S500_CMU_H
+
+#define CLK_NONE               0
+
+/* fixed rate clocks */
+#define CLK_LOSC               1
+#define CLK_HOSC               2
+
+/* pll clocks */
+#define CLK_CORE_PLL           3
+#define CLK_DEV_PLL            4
+#define CLK_DDR_PLL            5
+#define CLK_NAND_PLL           6
+#define CLK_DISPLAY_PLL                7
+#define CLK_ETHERNET_PLL       8
+#define CLK_AUDIO_PLL          9
+
+/* system clock */
+#define CLK_DEV                        10
+#define CLK_H                  11
+#define CLK_AHBPREDIV          12
+#define CLK_AHB                        13
+#define CLK_DE                 14
+#define CLK_BISP               15
+#define CLK_VCE                        16
+#define CLK_VDE                        17
+
+/* peripheral device clock */
+#define CLK_TIMER              18
+#define CLK_I2C0               19
+#define CLK_I2C1               20
+#define CLK_I2C2               21
+#define CLK_I2C3               22
+#define CLK_PWM0               23
+#define CLK_PWM1               24
+#define CLK_PWM2               25
+#define CLK_PWM3               26
+#define CLK_PWM4               27
+#define CLK_PWM5               28
+#define CLK_SD0                        29
+#define CLK_SD1                        30
+#define CLK_SD2                        31
+#define CLK_SENSOR0            32
+#define CLK_SENSOR1            33
+#define CLK_SPI0               34
+#define CLK_SPI1               35
+#define CLK_SPI2               36
+#define CLK_SPI3               37
+#define CLK_UART0              38
+#define CLK_UART1              39
+#define CLK_UART2              40
+#define CLK_UART3              41
+#define CLK_UART4              42
+#define CLK_UART5              43
+#define CLK_UART6              44
+#define CLK_DE1                        45
+#define CLK_DE2                        46
+#define CLK_I2SRX              47
+#define CLK_I2STX              48
+#define CLK_HDMI_AUDIO         49
+#define CLK_HDMI               50
+#define CLK_SPDIF              51
+#define CLK_NAND               52
+#define CLK_ECC                        53
+#define CLK_RMII_REF           54
+
+#define CLK_NR_CLKS           (CLK_RMII_REF + 1)
+
+#endif /* __DT_BINDINGS_CLOCK_S500_CMU_H */
index 6195501..8ec4a26 100644 (file)
 #define CLKID_AO_SAR_ADC_SEL   8
 #define CLKID_AO_SAR_ADC_DIV   9
 #define CLKID_AO_SAR_ADC_CLK   10
-#define CLKID_AO_ALT_XTAL      11
+#define CLKID_AO_CTS_OSCIN     11
+#define CLKID_AO_32K_PRE       12
+#define CLKID_AO_32K_DIV       13
+#define CLKID_AO_32K_SEL       14
+#define CLKID_AO_32K           15
+#define CLKID_AO_CTS_RTC_OSCIN 16
 
 #endif
index 98bd85c..25ffa53 100644 (file)
 #define CLK_ACLK_G2D_266               220
 #define CLK_ACLK_G2D_400               221
 #define CLK_ACLK_G3D_400               222
-#define CLK_ACLK_IMEM_SSX_266          223
+#define CLK_ACLK_IMEM_SSSX_266         223
 #define CLK_ACLK_BUS0_400              224
 #define CLK_ACLK_BUS1_400              225
 #define CLK_ACLK_IMEM_200              226
 
 #define CAM1_NR_CLK                                    113
 
+/* CMU_IMEM */
+#define CLK_ACLK_SLIMSSS               2
+#define CLK_PCLK_SLIMSSS               35
+
+#define IMEM_NR_CLK                    36
+
 #endif /* _DT_BINDINGS_CLOCK_EXYNOS5433_H */
diff --git a/include/dt-bindings/clock/g12a-aoclkc.h b/include/dt-bindings/clock/g12a-aoclkc.h
new file mode 100644 (file)
index 0000000..8db01ff
--- /dev/null
@@ -0,0 +1,34 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright (c) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ *
+ * Copyright (c) 2018 Amlogic, inc.
+ * Author: Qiufang Dai <qiufang.dai@amlogic.com>
+ */
+
+#ifndef DT_BINDINGS_CLOCK_AMLOGIC_MESON_G12A_AOCLK
+#define DT_BINDINGS_CLOCK_AMLOGIC_MESON_G12A_AOCLK
+
+#define CLKID_AO_AHB           0
+#define CLKID_AO_IR_IN         1
+#define CLKID_AO_I2C_M0                2
+#define CLKID_AO_I2C_S0                3
+#define CLKID_AO_UART          4
+#define CLKID_AO_PROD_I2C      5
+#define CLKID_AO_UART2         6
+#define CLKID_AO_IR_OUT                7
+#define CLKID_AO_SAR_ADC       8
+#define CLKID_AO_MAILBOX       9
+#define CLKID_AO_M3            10
+#define CLKID_AO_AHB_SRAM      11
+#define CLKID_AO_RTI           12
+#define CLKID_AO_M4_FCLK       13
+#define CLKID_AO_M4_HCLK       14
+#define CLKID_AO_CLK81         15
+#define CLKID_AO_SAR_ADC_CLK   18
+#define CLKID_AO_32K           23
+#define CLKID_AO_CEC           27
+#define CLKID_AO_CTS_RTC_OSCIN 28
+
+#endif
diff --git a/include/dt-bindings/clock/g12a-clkc.h b/include/dt-bindings/clock/g12a-clkc.h
new file mode 100644 (file)
index 0000000..83b6570
--- /dev/null
@@ -0,0 +1,135 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR MIT */
+/*
+ * Meson-G12A clock tree IDs
+ *
+ * Copyright (c) 2018 Amlogic, Inc. All rights reserved.
+ */
+
+#ifndef __G12A_CLKC_H
+#define __G12A_CLKC_H
+
+#define CLKID_SYS_PLL                          0
+#define CLKID_FIXED_PLL                                1
+#define CLKID_FCLK_DIV2                                2
+#define CLKID_FCLK_DIV3                                3
+#define CLKID_FCLK_DIV4                                4
+#define CLKID_FCLK_DIV5                                5
+#define CLKID_FCLK_DIV7                                6
+#define CLKID_GP0_PLL                          7
+#define CLKID_CLK81                            10
+#define CLKID_MPLL0                            11
+#define CLKID_MPLL1                            12
+#define CLKID_MPLL2                            13
+#define CLKID_MPLL3                            14
+#define CLKID_DDR                              15
+#define CLKID_DOS                              16
+#define CLKID_AUDIO_LOCKER                     17
+#define CLKID_MIPI_DSI_HOST                    18
+#define CLKID_ETH_PHY                          19
+#define CLKID_ISA                              20
+#define CLKID_PL301                            21
+#define CLKID_PERIPHS                          22
+#define CLKID_SPICC0                           23
+#define CLKID_I2C                              24
+#define CLKID_SANA                             25
+#define CLKID_SD                               26
+#define CLKID_RNG0                             27
+#define CLKID_UART0                            28
+#define CLKID_SPICC1                           29
+#define CLKID_HIU_IFACE                                30
+#define CLKID_MIPI_DSI_PHY                     31
+#define CLKID_ASSIST_MISC                      32
+#define CLKID_SD_EMMC_A                                33
+#define CLKID_SD_EMMC_B                                34
+#define CLKID_SD_EMMC_C                                35
+#define CLKID_AUDIO_CODEC                      36
+#define CLKID_AUDIO                            37
+#define CLKID_ETH                              38
+#define CLKID_DEMUX                            39
+#define CLKID_AUDIO_IFIFO                      40
+#define CLKID_ADC                              41
+#define CLKID_UART1                            42
+#define CLKID_G2D                              43
+#define CLKID_RESET                            44
+#define CLKID_PCIE_COMB                                45
+#define CLKID_PARSER                           46
+#define CLKID_USB                              47
+#define CLKID_PCIE_PHY                         48
+#define CLKID_AHB_ARB0                         49
+#define CLKID_AHB_DATA_BUS                     50
+#define CLKID_AHB_CTRL_BUS                     51
+#define CLKID_HTX_HDCP22                       52
+#define CLKID_HTX_PCLK                         53
+#define CLKID_BT656                            54
+#define CLKID_USB1_DDR_BRIDGE                  55
+#define CLKID_MMC_PCLK                         56
+#define CLKID_UART2                            57
+#define CLKID_VPU_INTR                         58
+#define CLKID_GIC                              59
+#define CLKID_SD_EMMC_A_CLK0                   60
+#define CLKID_SD_EMMC_B_CLK0                   61
+#define CLKID_SD_EMMC_C_CLK0                   62
+#define CLKID_HIFI_PLL                         74
+#define CLKID_VCLK2_VENCI0                     80
+#define CLKID_VCLK2_VENCI1                     81
+#define CLKID_VCLK2_VENCP0                     82
+#define CLKID_VCLK2_VENCP1                     83
+#define CLKID_VCLK2_VENCT0                     84
+#define CLKID_VCLK2_VENCT1                     85
+#define CLKID_VCLK2_OTHER                      86
+#define CLKID_VCLK2_ENCI                       87
+#define CLKID_VCLK2_ENCP                       88
+#define CLKID_DAC_CLK                          89
+#define CLKID_AOCLK                            90
+#define CLKID_IEC958                           91
+#define CLKID_ENC480P                          92
+#define CLKID_RNG1                             93
+#define CLKID_VCLK2_ENCT                       94
+#define CLKID_VCLK2_ENCL                       95
+#define CLKID_VCLK2_VENCLMMC                   96
+#define CLKID_VCLK2_VENCL                      97
+#define CLKID_VCLK2_OTHER1                     98
+#define CLKID_FCLK_DIV2P5                      99
+#define CLKID_DMA                              105
+#define CLKID_EFUSE                            106
+#define CLKID_ROM_BOOT                         107
+#define CLKID_RESET_SEC                                108
+#define CLKID_SEC_AHB_APB3                     109
+#define CLKID_VPU_0_SEL                                110
+#define CLKID_VPU_0                            112
+#define CLKID_VPU_1_SEL                                113
+#define CLKID_VPU_1                            115
+#define CLKID_VPU                              116
+#define CLKID_VAPB_0_SEL                       117
+#define CLKID_VAPB_0                           119
+#define CLKID_VAPB_1_SEL                       120
+#define CLKID_VAPB_1                           122
+#define CLKID_VAPB_SEL                         123
+#define CLKID_VAPB                             124
+#define CLKID_HDMI_PLL                         128
+#define CLKID_VID_PLL                          129
+#define CLKID_VCLK                             138
+#define CLKID_VCLK2                            139
+#define CLKID_VCLK_DIV1                                148
+#define CLKID_VCLK_DIV2                                149
+#define CLKID_VCLK_DIV4                                150
+#define CLKID_VCLK_DIV6                                151
+#define CLKID_VCLK_DIV12                       152
+#define CLKID_VCLK2_DIV1                       153
+#define CLKID_VCLK2_DIV2                       154
+#define CLKID_VCLK2_DIV4                       155
+#define CLKID_VCLK2_DIV6                       156
+#define CLKID_VCLK2_DIV12                      157
+#define CLKID_CTS_ENCI                         162
+#define CLKID_CTS_ENCP                         163
+#define CLKID_CTS_VDAC                         164
+#define CLKID_HDMI_TX                          165
+#define CLKID_HDMI                             168
+#define CLKID_MALI_0_SEL                       169
+#define CLKID_MALI_0                           171
+#define CLKID_MALI_1_SEL                       172
+#define CLKID_MALI_1                           174
+#define CLKID_MALI                             175
+#define CLKID_MPLL_5OM                         177
+
+#endif /* __G12A_CLKC_H */
index 9d15e22..ec3b263 100644 (file)
 #define CLKID_AO_UART2         4
 #define CLKID_AO_IR_BLASTER    5
 #define CLKID_AO_CEC_32K       6
+#define CLKID_AO_CTS_OSCIN     7
+#define CLKID_AO_32K_PRE       8
+#define CLKID_AO_32K_DIV       9
+#define CLKID_AO_32K_SEL       10
+#define CLKID_AO_32K           11
+#define CLKID_AO_CTS_RTC_OSCIN 12
+#define CLKID_AO_CLK81         13
 
 #endif
index d382fc7..a81be5b 100644 (file)
 #define IMX5_CLK_IEEE1588_SEL          202
 #define IMX5_CLK_IEEE1588_PODF         203
 #define IMX5_CLK_IEEE1588_GATE         204
-#define IMX5_CLK_END                   205
+#define IMX5_CLK_SCC2_IPG_GATE         205
+#define IMX5_CLK_END                   206
 
 #endif /* __DT_BINDINGS_CLOCK_IMX5_H */
diff --git a/include/dt-bindings/clock/imx8mm-clock.h b/include/dt-bindings/clock/imx8mm-clock.h
new file mode 100644 (file)
index 0000000..1b4353e
--- /dev/null
@@ -0,0 +1,244 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/*
+ * Copyright 2017-2018 NXP
+ */
+
+#ifndef __DT_BINDINGS_CLOCK_IMX8MM_H
+#define __DT_BINDINGS_CLOCK_IMX8MM_H
+
+#define IMX8MM_CLK_DUMMY                       0
+#define IMX8MM_CLK_32K                         1
+#define IMX8MM_CLK_24M                         2
+#define IMX8MM_OSC_HDMI_CLK                    3
+#define IMX8MM_CLK_EXT1                                4
+#define IMX8MM_CLK_EXT2                                5
+#define IMX8MM_CLK_EXT3                                6
+#define IMX8MM_CLK_EXT4                                7
+#define IMX8MM_AUDIO_PLL1_REF_SEL              8
+#define IMX8MM_AUDIO_PLL2_REF_SEL              9
+#define IMX8MM_VIDEO_PLL1_REF_SEL              10
+#define IMX8MM_DRAM_PLL_REF_SEL                        11
+#define IMX8MM_GPU_PLL_REF_SEL                 12
+#define IMX8MM_VPU_PLL_REF_SEL                 13
+#define IMX8MM_ARM_PLL_REF_SEL                 14
+#define IMX8MM_SYS_PLL1_REF_SEL                        15
+#define IMX8MM_SYS_PLL2_REF_SEL                        16
+#define IMX8MM_SYS_PLL3_REF_SEL                        17
+#define IMX8MM_AUDIO_PLL1                      18
+#define IMX8MM_AUDIO_PLL2                      19
+#define IMX8MM_VIDEO_PLL1                      20
+#define IMX8MM_DRAM_PLL                                21
+#define IMX8MM_GPU_PLL                         22
+#define IMX8MM_VPU_PLL                         23
+#define IMX8MM_ARM_PLL                         24
+#define IMX8MM_SYS_PLL1                                25
+#define IMX8MM_SYS_PLL2                                26
+#define IMX8MM_SYS_PLL3                                27
+#define IMX8MM_AUDIO_PLL1_BYPASS               28
+#define IMX8MM_AUDIO_PLL2_BYPASS               29
+#define IMX8MM_VIDEO_PLL1_BYPASS               30
+#define IMX8MM_DRAM_PLL_BYPASS                 31
+#define IMX8MM_GPU_PLL_BYPASS                  32
+#define IMX8MM_VPU_PLL_BYPASS                  33
+#define IMX8MM_ARM_PLL_BYPASS                  34
+#define IMX8MM_SYS_PLL1_BYPASS                 35
+#define IMX8MM_SYS_PLL2_BYPASS                 36
+#define IMX8MM_SYS_PLL3_BYPASS                 37
+#define IMX8MM_AUDIO_PLL1_OUT                  38
+#define IMX8MM_AUDIO_PLL2_OUT                  39
+#define IMX8MM_VIDEO_PLL1_OUT                  40
+#define IMX8MM_DRAM_PLL_OUT                    41
+#define IMX8MM_GPU_PLL_OUT                     42
+#define IMX8MM_VPU_PLL_OUT                     43
+#define IMX8MM_ARM_PLL_OUT                     44
+#define IMX8MM_SYS_PLL1_OUT                    45
+#define IMX8MM_SYS_PLL2_OUT                    46
+#define IMX8MM_SYS_PLL3_OUT                    47
+#define IMX8MM_SYS_PLL1_40M                    48
+#define IMX8MM_SYS_PLL1_80M                    49
+#define IMX8MM_SYS_PLL1_100M                   50
+#define IMX8MM_SYS_PLL1_133M                   51
+#define IMX8MM_SYS_PLL1_160M                   52
+#define IMX8MM_SYS_PLL1_200M                   53
+#define IMX8MM_SYS_PLL1_266M                   54
+#define IMX8MM_SYS_PLL1_400M                   55
+#define IMX8MM_SYS_PLL1_800M                   56
+#define IMX8MM_SYS_PLL2_50M                    57
+#define IMX8MM_SYS_PLL2_100M                   58
+#define IMX8MM_SYS_PLL2_125M                   59
+#define IMX8MM_SYS_PLL2_166M                   60
+#define IMX8MM_SYS_PLL2_200M                   61
+#define IMX8MM_SYS_PLL2_250M                   62
+#define IMX8MM_SYS_PLL2_333M                   63
+#define IMX8MM_SYS_PLL2_500M                   64
+#define IMX8MM_SYS_PLL2_1000M                  65
+
+/* core */
+#define IMX8MM_CLK_A53_SRC                     66
+#define IMX8MM_CLK_M4_SRC                      67
+#define IMX8MM_CLK_VPU_SRC                     68
+#define IMX8MM_CLK_GPU3D_SRC                   69
+#define IMX8MM_CLK_GPU2D_SRC                   70
+#define IMX8MM_CLK_A53_CG                      71
+#define IMX8MM_CLK_M4_CG                       72
+#define IMX8MM_CLK_VPU_CG                      73
+#define IMX8MM_CLK_GPU3D_CG                    74
+#define IMX8MM_CLK_GPU2D_CG                    75
+#define IMX8MM_CLK_A53_DIV                     76
+#define IMX8MM_CLK_M4_DIV                      77
+#define IMX8MM_CLK_VPU_DIV                     78
+#define IMX8MM_CLK_GPU3D_DIV                   79
+#define IMX8MM_CLK_GPU2D_DIV                   80
+
+/* bus */
+#define IMX8MM_CLK_MAIN_AXI                    81
+#define IMX8MM_CLK_ENET_AXI                    82
+#define IMX8MM_CLK_NAND_USDHC_BUS              83
+#define IMX8MM_CLK_VPU_BUS                     84
+#define IMX8MM_CLK_DISP_AXI                    85
+#define IMX8MM_CLK_DISP_APB                    86
+#define IMX8MM_CLK_DISP_RTRM                   87
+#define IMX8MM_CLK_USB_BUS                     88
+#define IMX8MM_CLK_GPU_AXI                     89
+#define IMX8MM_CLK_GPU_AHB                     90
+#define IMX8MM_CLK_NOC                         91
+#define IMX8MM_CLK_NOC_APB                     92
+
+#define IMX8MM_CLK_AHB                         93
+#define IMX8MM_CLK_AUDIO_AHB                   94
+#define IMX8MM_CLK_IPG_ROOT                    95
+#define IMX8MM_CLK_IPG_AUDIO_ROOT              96
+
+#define IMX8MM_CLK_DRAM_ALT                    97
+#define IMX8MM_CLK_DRAM_APB                    98
+#define IMX8MM_CLK_VPU_G1                      99
+#define IMX8MM_CLK_VPU_G2                      100
+#define IMX8MM_CLK_DISP_DTRC                   101
+#define IMX8MM_CLK_DISP_DC8000                 102
+#define IMX8MM_CLK_PCIE1_CTRL                  103
+#define IMX8MM_CLK_PCIE1_PHY                   104
+#define IMX8MM_CLK_PCIE1_AUX                   105
+#define IMX8MM_CLK_DC_PIXEL                    106
+#define IMX8MM_CLK_LCDIF_PIXEL                 107
+#define IMX8MM_CLK_SAI1                                108
+#define IMX8MM_CLK_SAI2                                109
+#define IMX8MM_CLK_SAI3                                110
+#define IMX8MM_CLK_SAI4                                111
+#define IMX8MM_CLK_SAI5                                112
+#define IMX8MM_CLK_SAI6                                113
+#define IMX8MM_CLK_SPDIF1                      114
+#define IMX8MM_CLK_SPDIF2                      115
+#define IMX8MM_CLK_ENET_REF                    116
+#define IMX8MM_CLK_ENET_TIMER                  117
+#define IMX8MM_CLK_ENET_PHY_REF                        118
+#define IMX8MM_CLK_NAND                                119
+#define IMX8MM_CLK_QSPI                                120
+#define IMX8MM_CLK_USDHC1                      121
+#define IMX8MM_CLK_USDHC2                      122
+#define IMX8MM_CLK_I2C1                                123
+#define IMX8MM_CLK_I2C2                                124
+#define IMX8MM_CLK_I2C3                                125
+#define IMX8MM_CLK_I2C4                                126
+#define IMX8MM_CLK_UART1                       127
+#define IMX8MM_CLK_UART2                       128
+#define IMX8MM_CLK_UART3                       129
+#define IMX8MM_CLK_UART4                       130
+#define IMX8MM_CLK_USB_CORE_REF                        131
+#define IMX8MM_CLK_USB_PHY_REF                 132
+#define IMX8MM_CLK_ECSPI1                      133
+#define IMX8MM_CLK_ECSPI2                      134
+#define IMX8MM_CLK_PWM1                                135
+#define IMX8MM_CLK_PWM2                                136
+#define IMX8MM_CLK_PWM3                                137
+#define IMX8MM_CLK_PWM4                                138
+#define IMX8MM_CLK_GPT1                                139
+#define IMX8MM_CLK_WDOG                                140
+#define IMX8MM_CLK_WRCLK                       141
+#define IMX8MM_CLK_DSI_CORE                    142
+#define IMX8MM_CLK_DSI_PHY_REF                 143
+#define IMX8MM_CLK_DSI_DBI                     144
+#define IMX8MM_CLK_USDHC3                      145
+#define IMX8MM_CLK_CSI1_CORE                   146
+#define IMX8MM_CLK_CSI1_PHY_REF                        147
+#define IMX8MM_CLK_CSI1_ESC                    148
+#define IMX8MM_CLK_CSI2_CORE                   149
+#define IMX8MM_CLK_CSI2_PHY_REF                        150
+#define IMX8MM_CLK_CSI2_ESC                    151
+#define IMX8MM_CLK_PCIE2_CTRL                  152
+#define IMX8MM_CLK_PCIE2_PHY                   153
+#define IMX8MM_CLK_PCIE2_AUX                   154
+#define IMX8MM_CLK_ECSPI3                      155
+#define IMX8MM_CLK_PDM                         156
+#define IMX8MM_CLK_VPU_H1                      157
+#define IMX8MM_CLK_CLKO1                       158
+
+#define IMX8MM_CLK_ECSPI1_ROOT                 159
+#define IMX8MM_CLK_ECSPI2_ROOT                 160
+#define IMX8MM_CLK_ECSPI3_ROOT                 161
+#define IMX8MM_CLK_ENET1_ROOT                  162
+#define IMX8MM_CLK_GPT1_ROOT                   163
+#define IMX8MM_CLK_I2C1_ROOT                   164
+#define IMX8MM_CLK_I2C2_ROOT                   165
+#define IMX8MM_CLK_I2C3_ROOT                   166
+#define IMX8MM_CLK_I2C4_ROOT                   167
+#define IMX8MM_CLK_OCOTP_ROOT                  168
+#define IMX8MM_CLK_PCIE1_ROOT                  169
+#define IMX8MM_CLK_PWM1_ROOT                   170
+#define IMX8MM_CLK_PWM2_ROOT                   171
+#define IMX8MM_CLK_PWM3_ROOT                   172
+#define IMX8MM_CLK_PWM4_ROOT                   173
+#define IMX8MM_CLK_QSPI_ROOT                   174
+#define IMX8MM_CLK_NAND_ROOT                   175
+#define IMX8MM_CLK_SAI1_ROOT                   176
+#define IMX8MM_CLK_SAI1_IPG                    177
+#define IMX8MM_CLK_SAI2_ROOT                   178
+#define IMX8MM_CLK_SAI2_IPG                    179
+#define IMX8MM_CLK_SAI3_ROOT                   180
+#define IMX8MM_CLK_SAI3_IPG                    181
+#define IMX8MM_CLK_SAI4_ROOT                   182
+#define IMX8MM_CLK_SAI4_IPG                    183
+#define IMX8MM_CLK_SAI5_ROOT                   184
+#define IMX8MM_CLK_SAI5_IPG                    185
+#define IMX8MM_CLK_SAI6_ROOT                   186
+#define IMX8MM_CLK_SAI6_IPG                    187
+#define IMX8MM_CLK_UART1_ROOT                  188
+#define IMX8MM_CLK_UART2_ROOT                  189
+#define IMX8MM_CLK_UART3_ROOT                  190
+#define IMX8MM_CLK_UART4_ROOT                  191
+#define IMX8MM_CLK_USB1_CTRL_ROOT              192
+#define IMX8MM_CLK_GPU3D_ROOT                  193
+#define IMX8MM_CLK_USDHC1_ROOT                 194
+#define IMX8MM_CLK_USDHC2_ROOT                 195
+#define IMX8MM_CLK_WDOG1_ROOT                  196
+#define IMX8MM_CLK_WDOG2_ROOT                  197
+#define IMX8MM_CLK_WDOG3_ROOT                  198
+#define IMX8MM_CLK_VPU_G1_ROOT                 199
+#define IMX8MM_CLK_GPU_BUS_ROOT                        200
+#define IMX8MM_CLK_VPU_H1_ROOT                 201
+#define IMX8MM_CLK_VPU_G2_ROOT                 202
+#define IMX8MM_CLK_PDM_ROOT                    203
+#define IMX8MM_CLK_DISP_ROOT                   204
+#define IMX8MM_CLK_DISP_AXI_ROOT               205
+#define IMX8MM_CLK_DISP_APB_ROOT               206
+#define IMX8MM_CLK_DISP_RTRM_ROOT              207
+#define IMX8MM_CLK_USDHC3_ROOT                 208
+#define IMX8MM_CLK_TMU_ROOT                    209
+#define IMX8MM_CLK_VPU_DEC_ROOT                        210
+#define IMX8MM_CLK_SDMA1_ROOT                  211
+#define IMX8MM_CLK_SDMA2_ROOT                  212
+#define IMX8MM_CLK_SDMA3_ROOT                  213
+#define IMX8MM_CLK_GPT_3M                      214
+#define IMX8MM_CLK_ARM                         215
+#define IMX8MM_CLK_PDM_IPG                     216
+#define IMX8MM_CLK_GPU2D_ROOT                  217
+#define IMX8MM_CLK_MU_ROOT                     218
+#define IMX8MM_CLK_CSI1_ROOT                   219
+
+#define IMX8MM_CLK_DRAM_CORE                   220
+#define IMX8MM_CLK_DRAM_ALT_ROOT               221
+
+#define IMX8MM_CLK_NAND_USDHC_BUS_RAWNAND_CLK  222
+
+#define IMX8MM_CLK_END                         223
+
+#endif
index b53be41..b58cc64 100644 (file)
 #define IMX8MQ_CLK_VPU_G2_ROOT                 241
 
 /* SCCG PLL GATE */
-#define IMX8MQ_SYS1_PLL_OUT                    232
+#define IMX8MQ_SYS1_PLL_OUT                    242
 #define IMX8MQ_SYS2_PLL_OUT                    243
 #define IMX8MQ_SYS3_PLL_OUT                    244
 #define IMX8MQ_DRAM_PLL_OUT                    245
 /* txesc clock */
 #define IMX8MQ_CLK_DSI_IPG_DIV                  256
 
-#define IMX8MQ_CLK_TMU_ROOT                    265
+#define IMX8MQ_CLK_TMU_ROOT                    257
 
 /* Display root clocks */
-#define IMX8MQ_CLK_DISP_AXI_ROOT               266
-#define IMX8MQ_CLK_DISP_APB_ROOT               267
-#define IMX8MQ_CLK_DISP_RTRM_ROOT              268
+#define IMX8MQ_CLK_DISP_AXI_ROOT               258
+#define IMX8MQ_CLK_DISP_APB_ROOT               259
+#define IMX8MQ_CLK_DISP_RTRM_ROOT              260
 
-#define IMX8MQ_CLK_OCOTP_ROOT                  269
+#define IMX8MQ_CLK_OCOTP_ROOT                  261
 
-#define IMX8MQ_CLK_DRAM_ALT_ROOT               270
-#define IMX8MQ_CLK_DRAM_CORE                   271
+#define IMX8MQ_CLK_DRAM_ALT_ROOT               262
+#define IMX8MQ_CLK_DRAM_CORE                   263
 
-#define IMX8MQ_CLK_MU_ROOT                     272
-#define IMX8MQ_VIDEO2_PLL_OUT                  273
+#define IMX8MQ_CLK_MU_ROOT                     264
+#define IMX8MQ_VIDEO2_PLL_OUT                  265
 
-#define IMX8MQ_CLK_CLKO2                       274
+#define IMX8MQ_CLK_CLKO2                       266
 
-#define IMX8MQ_CLK_NAND_USDHC_BUS_RAWNAND_CLK  275
+#define IMX8MQ_CLK_NAND_USDHC_BUS_RAWNAND_CLK  267
 
-#define IMX8MQ_CLK_END                         276
+#define IMX8MQ_CLK_CLKO1                       268
+#define IMX8MQ_CLK_ARM                         269
+
+#define IMX8MQ_CLK_GPIO1_ROOT                  270
+#define IMX8MQ_CLK_GPIO2_ROOT                  271
+#define IMX8MQ_CLK_GPIO3_ROOT                  272
+#define IMX8MQ_CLK_GPIO4_ROOT                  273
+#define IMX8MQ_CLK_GPIO5_ROOT                  274
+
+#define IMX8MQ_CLK_END                         275
 #endif /* __DT_BINDINGS_CLOCK_IMX8MQ_H */
index 7b24fc7..e785c6e 100644 (file)
@@ -71,7 +71,7 @@
 #define MMP2_CLK_CCIC1_MIX             117
 #define MMP2_CLK_CCIC1_PHY             118
 #define MMP2_CLK_CCIC1_SPHY            119
-#define MMP2_CLK_SP                    120
+#define MMP2_CLK_DISP0_LCDC            120
 
 #define MMP2_NR_CLKS                   200
 #endif
index 5fe2923..8067077 100644 (file)
 #define CLKID_MPLL2            95
 #define CLKID_NAND_CLK         112
 #define CLKID_ABP              124
+#define CLKID_APB              124
 #define CLKID_PERIPH           126
 #define CLKID_AXI              128
 #define CLKID_L2_DRAM          130
index 8aea623..76e4e5b 100644 (file)
 #define CLK_INFRA_PMICWRAP             11
 #define CLK_INFRA_CLK_13M              12
 #define CLK_INFRA_CA53SEL               13
-#define CLK_INFRA_CA57SEL               14
+#define CLK_INFRA_CA57SEL               14 /* Deprecated. Don't use it. */
+#define CLK_INFRA_CA72SEL               14
 #define CLK_INFRA_NR_CLK                15
 
 /* PERI_SYS */
index 3658b0c..ede93a0 100644 (file)
 #define RPM_SMD_BIMC_GPU_A_CLK                 77
 #define RPM_SMD_QPIC_CLK                       78
 #define RPM_SMD_QPIC_CLK_A                     79
+#define RPM_SMD_LN_BB_CLK1                     80
+#define RPM_SMD_LN_BB_CLK1_A                   81
+#define RPM_SMD_LN_BB_CLK2                     82
+#define RPM_SMD_LN_BB_CLK2_A                   83
+#define RPM_SMD_LN_BB_CLK3_PIN                 84
+#define RPM_SMD_LN_BB_CLK3_A_PIN               85
+#define RPM_SMD_RF_CLK3                                86
+#define RPM_SMD_RF_CLK3_A                      87
+#define RPM_SMD_RF_CLK3_PIN                    88
+#define RPM_SMD_RF_CLK3_A_PIN                  89
 
 #endif
index f48fbd6..edcab3f 100644 (file)
@@ -18,5 +18,6 @@
 #define RPMH_RF_CLK2_A                         9
 #define RPMH_RF_CLK3                           10
 #define RPMH_RF_CLK3_A                         11
+#define RPMH_IPA_CLK                           12
 
 #endif
index 9bc5d45..e355363 100644 (file)
@@ -54,5 +54,6 @@
 #define R8A774A1_CLK_CPEX              43
 #define R8A774A1_CLK_R                 44
 #define R8A774A1_CLK_OSC               45
+#define R8A774A1_CLK_CANFD             46
 
 #endif /* __DT_BINDINGS_CLOCK_R8A774A1_CPG_MSSR_H__ */
index 8fe51b6..8ad9cd6 100644 (file)
@@ -56,5 +56,6 @@
 #define R8A774C0_CLK_CSI0              45
 #define R8A774C0_CLK_CP                        46
 #define R8A774C0_CLK_CPEX              47
+#define R8A774C0_CLK_CANFD             48
 
 #endif /* __DT_BINDINGS_CLOCK_R8A774C0_CPG_MSSR_H__ */
index 90ec780..4cdaf13 100644 (file)
 
 #define STM32MP1_LAST_CLK 232
 
-#define LTDC_K         LTDC_PX
-#define ETHMAC_K       ETHCK_K
-
 #endif /* _DT_BINDINGS_STM32MP1_CLKS_H_ */
index ad6f55d..0f2e0fe 100644 (file)
@@ -1,12 +1,11 @@
+/* SPDX-License-Identifier: GPL-2.0+ OR BSD-3-Clause */
 /*
- *
  * Copyright (c) 2016 BayLibre, SAS.
  * Author: Neil Armstrong <narmstrong@baylibre.com>
  *
  * Copyright (c) 2017 Amlogic, inc.
  * Author: Yixun Lan <yixun.lan@amlogic.com>
  *
- * SPDX-License-Identifier: (GPL-2.0+ OR BSD)
  */
 
 #ifndef _DT_BINDINGS_AMLOGIC_MESON_AXG_RESET_H
diff --git a/include/dt-bindings/reset/g12a-aoclkc.h b/include/dt-bindings/reset/g12a-aoclkc.h
new file mode 100644 (file)
index 0000000..bd2e233
--- /dev/null
@@ -0,0 +1,18 @@
+/* SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) */
+/*
+ * Copyright (c) 2016 BayLibre, SAS
+ * Author: Neil Armstrong <narmstrong@baylibre.com>
+ */
+
+#ifndef DT_BINDINGS_RESET_AMLOGIC_MESON_G12A_AOCLK
+#define DT_BINDINGS_RESET_AMLOGIC_MESON_G12A_AOCLK
+
+#define RESET_AO_IR_IN         0
+#define RESET_AO_UART          1
+#define RESET_AO_I2C_M         2
+#define RESET_AO_I2C_S         3
+#define RESET_AO_SAR_ADC       4
+#define RESET_AO_UART2         5
+#define RESET_AO_IR_OUT                6
+
+#endif
diff --git a/include/keys/request_key_auth-type.h b/include/keys/request_key_auth-type.h
new file mode 100644 (file)
index 0000000..a726dd3
--- /dev/null
@@ -0,0 +1,36 @@
+/* request_key authorisation token key type
+ *
+ * Copyright (C) 2005 Red Hat, Inc. All Rights Reserved.
+ * Written by David Howells (dhowells@redhat.com)
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public Licence
+ * as published by the Free Software Foundation; either version
+ * 2 of the Licence, or (at your option) any later version.
+ */
+
+#ifndef _KEYS_REQUEST_KEY_AUTH_TYPE_H
+#define _KEYS_REQUEST_KEY_AUTH_TYPE_H
+
+#include <linux/key.h>
+
+/*
+ * Authorisation record for request_key().
+ */
+struct request_key_auth {
+       struct key              *target_key;
+       struct key              *dest_keyring;
+       const struct cred       *cred;
+       void                    *callout_info;
+       size_t                  callout_len;
+       pid_t                   pid;
+       char                    op[8];
+} __randomize_layout;
+
+static inline struct request_key_auth *get_request_key_auth(const struct key *key)
+{
+       return key->payload.data[0];
+}
+
+
+#endif /* _KEYS_REQUEST_KEY_AUTH_TYPE_H */
index e098cbe..12babe9 100644 (file)
@@ -31,7 +31,7 @@
 struct user_key_payload {
        struct rcu_head rcu;            /* RCU destructor */
        unsigned short  datalen;        /* length of this data */
-       char            data[0];        /* actual data */
+       char            data[0] __aligned(__alignof__(u64)); /* actual data */
 };
 
 extern struct key_type key_type_user;
index 4f31f96..c36c86f 100644 (file)
@@ -100,7 +100,7 @@ enum vgic_irq_config {
 };
 
 struct vgic_irq {
-       spinlock_t irq_lock;            /* Protects the content of the struct */
+       raw_spinlock_t irq_lock;        /* Protects the content of the struct */
        struct list_head lpi_list;      /* Used to link all LPIs together */
        struct list_head ap_list;
 
@@ -256,7 +256,7 @@ struct vgic_dist {
        u64                     propbaser;
 
        /* Protects the lpi_list and the count value below. */
-       spinlock_t              lpi_list_lock;
+       raw_spinlock_t          lpi_list_lock;
        struct list_head        lpi_list_head;
        int                     lpi_list_count;
 
@@ -307,7 +307,7 @@ struct vgic_cpu {
        unsigned int used_lrs;
        struct vgic_irq private_irqs[VGIC_NR_PRIVATE_IRQS];
 
-       spinlock_t ap_list_lock;        /* Protects the ap_list */
+       raw_spinlock_t ap_list_lock;    /* Protects the ap_list */
 
        /*
         * List of IRQs that this VCPU should consider because they are either
index c311571..07e02d6 100644 (file)
@@ -190,6 +190,7 @@ struct backing_dev_info {
        struct radix_tree_root cgwb_tree; /* radix tree of active cgroup wbs */
        struct rb_root cgwb_congested_tree; /* their congested states */
        struct mutex cgwb_release_mutex;  /* protect shutdown of wb structs */
+       struct rw_semaphore wb_switch_rwsem; /* no cgwb switch while syncing */
 #else
        struct bdi_writeback_congested *wb_congested;
 #endif
index 7cca5f8..f3c4351 100644 (file)
@@ -6,6 +6,7 @@
 
 struct bcma_soc {
        struct bcma_bus bus;
+       struct device *dev;
 };
 
 int __init bcma_host_soc_register(struct bcma_soc *soc);
index 5c7e7f8..d66bf5f 100644 (file)
@@ -287,7 +287,7 @@ enum req_opf {
        REQ_OP_DISCARD          = 3,
        /* securely erase sectors */
        REQ_OP_SECURE_ERASE     = 5,
-       /* seset a zone write pointer */
+       /* reset a zone write pointer */
        REQ_OP_ZONE_RESET       = 6,
        /* write the same sector many times */
        REQ_OP_WRITE_SAME       = 7,
index 8804753..7bb2d8d 100644 (file)
@@ -116,7 +116,13 @@ extern void blk_fill_rwbs(char *rwbs, unsigned int op, int bytes);
 
 static inline sector_t blk_rq_trace_sector(struct request *rq)
 {
-       return blk_rq_is_passthrough(rq) ? 0 : blk_rq_pos(rq);
+       /*
+        * Tracing should ignore starting sector for passthrough requests and
+        * requests where starting sector didn't get set.
+        */
+       if (blk_rq_is_passthrough(rq) || blk_rq_pos(rq) == (sector_t)-1)
+               return 0;
+       return blk_rq_pos(rq);
 }
 
 static inline unsigned int blk_rq_trace_nr_sectors(struct request *rq)
index 27b7494..573cca0 100644 (file)
@@ -172,6 +172,7 @@ struct bpf_verifier_state_list {
 #define BPF_ALU_SANITIZE_SRC           1U
 #define BPF_ALU_SANITIZE_DST           2U
 #define BPF_ALU_NEG_VALUE              (1U << 2)
+#define BPF_ALU_NON_POINTER            (1U << 3)
 #define BPF_ALU_SANITIZE               (BPF_ALU_SANITIZE_SRC | \
                                         BPF_ALU_SANITIZE_DST)
 
index f02cee0..d815622 100644 (file)
@@ -3,13 +3,22 @@
 #define _LINUX_BPFILTER_H
 
 #include <uapi/linux/bpfilter.h>
+#include <linux/umh.h>
 
 struct sock;
 int bpfilter_ip_set_sockopt(struct sock *sk, int optname, char __user *optval,
                            unsigned int optlen);
 int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval,
                            int __user *optlen);
-extern int (*bpfilter_process_sockopt)(struct sock *sk, int optname,
-                                      char __user *optval,
-                                      unsigned int optlen, bool is_set);
+struct bpfilter_umh_ops {
+       struct umh_info info;
+       /* since ip_getsockopt() can run in parallel, serialize access to umh */
+       struct mutex lock;
+       int (*sockopt)(struct sock *sk, int optname,
+                      char __user *optval,
+                      unsigned int optlen, bool is_set);
+       int (*start)(void);
+       bool stop;
+};
+extern struct bpfilter_umh_ops bpfilter_ops;
 #endif
index 68bb09c..a420c07 100644 (file)
@@ -35,6 +35,7 @@
 #define CEPH_OPT_NOMSGAUTH       (1<<4) /* don't require msg signing feat */
 #define CEPH_OPT_TCP_NODELAY     (1<<5) /* TCP_NODELAY on TCP sockets */
 #define CEPH_OPT_NOMSGSIGN       (1<<6) /* don't sign msgs */
+#define CEPH_OPT_ABORT_ON_FULL   (1<<7) /* abort w/ ENOSPC when full */
 
 #define CEPH_OPT_DEFAULT   (CEPH_OPT_TCP_NODELAY)
 
@@ -53,7 +54,7 @@ struct ceph_options {
        unsigned long osd_request_timeout;      /* jiffies */
 
        /*
-        * any type that can't be simply compared or doesn't need need
+        * any type that can't be simply compared or doesn't need
         * to be compared should go beyond this point,
         * ceph_compare_options() should be updated accordingly
         */
@@ -281,7 +282,8 @@ extern struct ceph_options *ceph_parse_options(char *options,
                              const char *dev_name, const char *dev_name_end,
                              int (*parse_extra_token)(char *c, void *private),
                              void *private);
-int ceph_print_client_options(struct seq_file *m, struct ceph_client *client);
+int ceph_print_client_options(struct seq_file *m, struct ceph_client *client,
+                             bool show_all);
 extern void ceph_destroy_options(struct ceph_options *opt);
 extern int ceph_compare_options(struct ceph_options *new_opt,
                                struct ceph_client *client);
index 7a2af50..2294f96 100644 (file)
@@ -354,7 +354,6 @@ struct ceph_osd_client {
        struct rb_root         linger_map_checks;
        atomic_t               num_requests;
        atomic_t               num_homeless;
-       bool                   abort_on_full; /* abort w/ ENOSPC when full */
        int                    abort_err;
        struct delayed_work    timeout_work;
        struct delayed_work    osds_timeout_work;
index e443fa9..b7cf80a 100644 (file)
@@ -792,6 +792,9 @@ unsigned int __clk_get_enable_count(struct clk *clk);
 unsigned long clk_hw_get_rate(const struct clk_hw *hw);
 unsigned long __clk_get_flags(struct clk *clk);
 unsigned long clk_hw_get_flags(const struct clk_hw *hw);
+#define clk_hw_can_set_rate_parent(hw) \
+       (clk_hw_get_flags((hw)) & CLK_SET_RATE_PARENT)
+
 bool clk_hw_is_prepared(const struct clk_hw *hw);
 bool clk_hw_rate_is_protected(const struct clk_hw *hw);
 bool clk_hw_is_enabled(const struct clk_hw *hw);
index a7773b5..d8bc1a8 100644 (file)
@@ -383,6 +383,17 @@ int __must_check devm_clk_bulk_get_all(struct device *dev,
  */
 struct clk *devm_clk_get(struct device *dev, const char *id);
 
+/**
+ * devm_clk_get_optional - lookup and obtain a managed reference to an optional
+ *                        clock producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Behaves the same as devm_clk_get() except where there is no clock producer.
+ * In this case, instead of returning -ENOENT, the function returns NULL.
+ */
+struct clk *devm_clk_get_optional(struct device *dev, const char *id);
+
 /**
  * devm_get_clk_from_child - lookup and obtain a managed reference to a
  *                          clock producer from child node.
@@ -718,6 +729,12 @@ static inline struct clk *devm_clk_get(struct device *dev, const char *id)
        return NULL;
 }
 
+static inline struct clk *devm_clk_get_optional(struct device *dev,
+                                               const char *id)
+{
+       return NULL;
+}
+
 static inline int __must_check devm_clk_bulk_get(struct device *dev, int num_clks,
                                                 struct clk_bulk_data *clks)
 {
@@ -862,6 +879,25 @@ static inline void clk_bulk_disable_unprepare(int num_clks,
        clk_bulk_unprepare(num_clks, clks);
 }
 
+/**
+ * clk_get_optional - lookup and obtain a reference to an optional clock
+ *                   producer.
+ * @dev: device for clock "consumer"
+ * @id: clock consumer ID
+ *
+ * Behaves the same as clk_get() except where there is no clock producer. In
+ * this case, instead of returning -ENOENT, the function returns NULL.
+ */
+static inline struct clk *clk_get_optional(struct device *dev, const char *id)
+{
+       struct clk *clk = clk_get(dev, id);
+
+       if (clk == ERR_PTR(-ENOENT))
+               return NULL;
+
+       return clk;
+}
+
 #if defined(CONFIG_OF) && defined(CONFIG_COMMON_CLK)
 struct clk *of_clk_get(struct device_node *np, int index);
 struct clk *of_clk_get_by_name(struct device_node *np, const char *name);
index eacc5df..78872ef 100644 (file)
@@ -160,6 +160,7 @@ struct clk_hw_omap {
        struct clockdomain      *clkdm;
        const struct clk_hw_omap_ops    *ops;
        u32                     context;
+       int                     autoidle_count;
 };
 
 /*
index 4890ff0..ccb32af 100644 (file)
@@ -52,4 +52,8 @@ int clk_add_alias(const char *, const char *, const char *, struct device *);
 int clk_register_clkdev(struct clk *, const char *, const char *);
 int clk_hw_register_clkdev(struct clk_hw *, const char *, const char *);
 
+int devm_clk_hw_register_clkdev(struct device *dev, struct clk_hw *hw,
+                               const char *con_id, const char *dev_id);
+void devm_clk_release_clkdev(struct device *dev, const char *con_id,
+                            const char *dev_id);
 #endif
index 39f668d..333a669 100644 (file)
@@ -3,9 +3,8 @@
 #error "Please don't include <linux/compiler-clang.h> directly, include <linux/compiler.h> instead."
 #endif
 
-/* Some compiler specific definitions are overwritten here
- * for Clang compiler
- */
+/* Compiler specific definitions for Clang compiler */
+
 #define uninitialized_var(x) x = *(&(x))
 
 /* same as gcc, this was present in clang-2.6 so we can assume it works
index 5776da4..e857941 100644 (file)
        (typeof(ptr)) (__ptr + (off));                                  \
 })
 
-/* Make the optimizer believe the variable can be manipulated arbitrarily. */
-#define OPTIMIZER_HIDE_VAR(var)                                                \
-       __asm__ ("" : "=r" (var) : "0" (var))
-
 /*
  * A trick to suppress uninitialized variable warning without generating any
  * code
  */
 #define uninitialized_var(x) x = x
 
-#ifdef RETPOLINE
+#ifdef CONFIG_RETPOLINE
 #define __noretpoline __attribute__((__indirect_branch__("keep")))
 #endif
 
index 517bd14..b17f3cd 100644 (file)
@@ -5,9 +5,7 @@
 
 #ifdef __ECC
 
-/* Some compiler specific definitions are overwritten here
- * for Intel ECC compiler
- */
+/* Compiler specific definitions for Intel ECC compiler */
 
 #include <asm/intrinsics.h>
 
index fc5004a..445348f 100644 (file)
@@ -161,7 +161,9 @@ void ftrace_likely_update(struct ftrace_likely_data *f, int val,
 #endif
 
 #ifndef OPTIMIZER_HIDE_VAR
-#define OPTIMIZER_HIDE_VAR(var) barrier()
+/* Make the optimizer believe the variable can be manipulated arbitrarily. */
+#define OPTIMIZER_HIDE_VAR(var)                                                \
+       __asm__ ("" : "=r" (var) : "0" (var))
 #endif
 
 /* Not-quite-unique ID. */
index 19f32b0..6b318ef 100644 (file)
@@ -34,6 +34,7 @@
 #ifndef __has_attribute
 # define __has_attribute(x) __GCC4_has_attribute_##x
 # define __GCC4_has_attribute___assume_aligned__      (__GNUC_MINOR__ >= 9)
+# define __GCC4_has_attribute___copy__                0
 # define __GCC4_has_attribute___designated_init__     0
 # define __GCC4_has_attribute___externally_visible__  1
 # define __GCC4_has_attribute___noclone__             1
  */
 #define __attribute_const__             __attribute__((__const__))
 
+/*
+ * Optional: only supported since gcc >= 9
+ * Optional: not supported by clang
+ * Optional: not supported by icc
+ *
+ *   gcc: https://gcc.gnu.org/onlinedocs/gcc/Common-Function-Attributes.html#index-copy-function-attribute
+ */
+#if __has_attribute(__copy__)
+# define __copy(symbol)                 __attribute__((__copy__(symbol)))
+#else
+# define __copy(symbol)
+#endif
+
 /*
  * Don't. Just don't. See commit 771c035372a0 ("deprecate the '__deprecated'
  * attribute warnings entirely and for good") for more information.
index 218df7f..5041357 100644 (file)
@@ -180,12 +180,10 @@ enum cpuhp_smt_control {
 #if defined(CONFIG_SMP) && defined(CONFIG_HOTPLUG_SMT)
 extern enum cpuhp_smt_control cpu_smt_control;
 extern void cpu_smt_disable(bool force);
-extern void cpu_smt_check_topology_early(void);
 extern void cpu_smt_check_topology(void);
 #else
 # define cpu_smt_control               (CPU_SMT_ENABLED)
 static inline void cpu_smt_disable(bool force) { }
-static inline void cpu_smt_check_topology_early(void) { }
 static inline void cpu_smt_check_topology(void) { }
 #endif
 
index ef4b70f..60996e6 100644 (file)
@@ -62,9 +62,10 @@ extern const struct qstr slash_name;
 struct dentry_stat_t {
        long nr_dentry;
        long nr_unused;
-       long age_limit;          /* age in seconds */
-       long want_pages;         /* pages requested by system */
-       long dummy[2];
+       long age_limit;         /* age in seconds */
+       long want_pages;        /* pages requested by system */
+       long nr_negative;       /* # of unused negative dentries */
+       long dummy;             /* Reserved for future use */
 };
 extern struct dentry_stat_t dentry_stat;
 
index cef2127..f6ded99 100644 (file)
@@ -717,15 +717,6 @@ static inline unsigned long dma_max_pfn(struct device *dev)
 }
 #endif
 
-/*
- * Please always use dma_alloc_coherent instead as it already zeroes the memory!
- */
-static inline void *dma_zalloc_coherent(struct device *dev, size_t size,
-                                       dma_addr_t *dma_handle, gfp_t flag)
-{
-       return dma_alloc_coherent(dev, size, dma_handle, flag);
-}
-
 static inline int dma_get_cache_alignment(void)
 {
 #ifdef ARCH_DMA_MINALIGN
index 45ff763..28604a8 100644 (file)
@@ -1198,8 +1198,6 @@ static inline bool efi_enabled(int feature)
 extern void efi_reboot(enum reboot_mode reboot_mode, const char *__unused);
 
 extern bool efi_is_table_address(unsigned long phys_addr);
-
-extern int efi_apply_persistent_mem_reservations(void);
 #else
 static inline bool efi_enabled(int feature)
 {
@@ -1218,11 +1216,6 @@ static inline bool efi_is_table_address(unsigned long phys_addr)
 {
        return false;
 }
-
-static inline int efi_apply_persistent_mem_reservations(void)
-{
-       return 0;
-}
 #endif
 
 extern int efi_status_to_err(efi_status_t status);
index 7cdd31a..f52ef0a 100644 (file)
@@ -653,6 +653,7 @@ extern int fb_new_modelist(struct fb_info *info);
 
 extern struct fb_info *registered_fb[FB_MAX];
 extern int num_registered_fb;
+extern bool fb_center_logo;
 extern struct class *fb_class;
 
 #define for_each_registered_fb(i)              \
index ad106d8..e532fcc 100644 (file)
@@ -591,8 +591,8 @@ static inline u8 *bpf_skb_cb(struct sk_buff *skb)
        return qdisc_skb_cb(skb)->data;
 }
 
-static inline u32 bpf_prog_run_save_cb(const struct bpf_prog *prog,
-                                      struct sk_buff *skb)
+static inline u32 __bpf_prog_run_save_cb(const struct bpf_prog *prog,
+                                        struct sk_buff *skb)
 {
        u8 *cb_data = bpf_skb_cb(skb);
        u8 cb_saved[BPF_SKB_CB_LEN];
@@ -611,15 +611,30 @@ static inline u32 bpf_prog_run_save_cb(const struct bpf_prog *prog,
        return res;
 }
 
+static inline u32 bpf_prog_run_save_cb(const struct bpf_prog *prog,
+                                      struct sk_buff *skb)
+{
+       u32 res;
+
+       preempt_disable();
+       res = __bpf_prog_run_save_cb(prog, skb);
+       preempt_enable();
+       return res;
+}
+
 static inline u32 bpf_prog_run_clear_cb(const struct bpf_prog *prog,
                                        struct sk_buff *skb)
 {
        u8 *cb_data = bpf_skb_cb(skb);
+       u32 res;
 
        if (unlikely(prog->cb_access))
                memset(cb_data, 0, BPF_SKB_CB_LEN);
 
-       return BPF_PROG_RUN(prog, skb);
+       preempt_disable();
+       res = BPF_PROG_RUN(prog, skb);
+       preempt_enable();
+       return res;
 }
 
 static __always_inline u32 bpf_prog_run_xdp(const struct bpf_prog *prog,
index 811c777..29d8e2c 100644 (file)
@@ -1479,11 +1479,12 @@ struct super_block {
        struct user_namespace *s_user_ns;
 
        /*
-        * Keep the lru lists last in the structure so they always sit on their
-        * own individual cachelines.
+        * The list_lru structure is essentially just a pointer to a table
+        * of per-node lru lists, each of which has its own spinlock.
+        * There is no need to put them into separate cachelines.
         */
-       struct list_lru         s_dentry_lru ____cacheline_aligned_in_smp;
-       struct list_lru         s_inode_lru ____cacheline_aligned_in_smp;
+       struct list_lru         s_dentry_lru;
+       struct list_lru         s_inode_lru;
        struct rcu_head         rcu;
        struct work_struct      destroy_work;
 
index 8663f21..2d6100e 100644 (file)
 
 #ifdef CONFIG_DEBUG_FS
 
+#include <linux/kfifo.h>
+
 #define HID_DEBUG_BUFSIZE 512
+#define HID_DEBUG_FIFOSIZE 512
 
 void hid_dump_input(struct hid_device *, struct hid_usage *, __s32);
 void hid_dump_report(struct hid_device *, int , u8 *, int);
@@ -37,11 +40,8 @@ void hid_debug_init(void);
 void hid_debug_exit(void);
 void hid_debug_event(struct hid_device *, char *);
 
-
 struct hid_debug_list {
-       char *hid_debug_buf;
-       int head;
-       int tail;
+       DECLARE_KFIFO_PTR(hid_debug_fifo, char);
        struct fasync_struct *fasync;
        struct hid_device *hdev;
        struct list_head node;
@@ -64,4 +64,3 @@ struct hid_debug_list {
 #endif
 
 #endif
-
index d992873..f9707d1 100644 (file)
@@ -430,7 +430,7 @@ struct hid_local {
  */
 
 struct hid_collection {
-       struct hid_collection *parent;
+       int parent_idx; /* device->collection */
        unsigned type;
        unsigned usage;
        unsigned level;
@@ -658,7 +658,6 @@ struct hid_parser {
        unsigned int         *collection_stack;
        unsigned int          collection_stack_ptr;
        unsigned int          collection_stack_size;
-       struct hid_collection *active_collection;
        struct hid_device    *device;
        unsigned int          scan_flags;
 };
index f0885cc..dcb6977 100644 (file)
@@ -1159,8 +1159,9 @@ struct hv_ring_buffer_debug_info {
        u32 bytes_avail_towrite;
 };
 
-void hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
-                           struct hv_ring_buffer_debug_info *debug_info);
+
+int hv_ringbuffer_get_debuginfo(const struct hv_ring_buffer_info *ring_info,
+                               struct hv_ring_buffer_debug_info *debug_info);
 
 /* Vmbus interface */
 #define vmbus_driver_register(driver)  \
index e7d29ae..971cf76 100644 (file)
@@ -615,6 +615,7 @@ struct ide_drive_s {
 
        /* current sense rq and buffer */
        bool sense_rq_armed;
+       bool sense_rq_active;
        struct request *sense_rq;
        struct request_sense sense_data;
 
@@ -1219,6 +1220,7 @@ extern void ide_stall_queue(ide_drive_t *drive, unsigned long timeout);
 extern void ide_timer_expiry(struct timer_list *t);
 extern irqreturn_t ide_intr(int irq, void *dev_id);
 extern blk_status_t ide_queue_rq(struct blk_mq_hw_ctx *, const struct blk_mq_queue_data *);
+extern blk_status_t ide_issue_rq(ide_drive_t *, struct request *, bool);
 extern void ide_requeue_and_plug(ide_drive_t *drive, struct request *rq);
 
 void ide_init_disk(struct gendisk *, ide_drive_t *);
index 6756fea..e44746d 100644 (file)
@@ -54,6 +54,7 @@ static inline bool dev_is_mac_header_xmit(const struct net_device *dev)
        case ARPHRD_IPGRE:
        case ARPHRD_VOID:
        case ARPHRD_NONE:
+       case ARPHRD_RAWIP:
                return false;
        default:
                return true;
index c672f34..4a728db 100644 (file)
@@ -260,6 +260,7 @@ struct irq_affinity {
 /**
  * struct irq_affinity_desc - Interrupt affinity descriptor
  * @mask:      cpumask to hold the affinity assignment
+ * @is_managed: 1 if the interrupt is managed internally
  */
 struct irq_affinity_desc {
        struct cpumask  mask;
index 071b4cb..c848a7c 100644 (file)
 #define GITS_TYPER_PLPIS               (1UL << 0)
 #define GITS_TYPER_VLPIS               (1UL << 1)
 #define GITS_TYPER_ITT_ENTRY_SIZE_SHIFT        4
-#define GITS_TYPER_ITT_ENTRY_SIZE(r)   ((((r) >> GITS_TYPER_ITT_ENTRY_SIZE_SHIFT) & 0x1f) + 1)
+#define GITS_TYPER_ITT_ENTRY_SIZE(r)   ((((r) >> GITS_TYPER_ITT_ENTRY_SIZE_SHIFT) & 0xf) + 1)
 #define GITS_TYPER_IDBITS_SHIFT                8
 #define GITS_TYPER_DEVBITS_SHIFT       13
 #define GITS_TYPER_DEVBITS(r)          ((((r) >> GITS_TYPER_DEVBITS_SHIFT) & 0x1f) + 1)
index bc9af55..e49d1de 100644 (file)
 struct kernel_pkey_query;
 struct kernel_pkey_params;
 
-/*
- * key under-construction record
- * - passed to the request_key actor if supplied
- */
-struct key_construction {
-       struct key      *key;   /* key being constructed */
-       struct key      *authkey;/* authorisation for key being constructed */
-};
-
 /*
  * Pre-parsed payload, used by key add, update and instantiate.
  *
@@ -50,8 +41,7 @@ struct key_preparsed_payload {
        time64_t        expiry;         /* Expiry time of key */
 } __randomize_layout;
 
-typedef int (*request_key_actor_t)(struct key_construction *key,
-                                  const char *op, void *aux);
+typedef int (*request_key_actor_t)(struct key *auth_key, void *aux);
 
 /*
  * Preparsed matching criterion.
@@ -181,20 +171,20 @@ extern int key_instantiate_and_link(struct key *key,
                                    const void *data,
                                    size_t datalen,
                                    struct key *keyring,
-                                   struct key *instkey);
+                                   struct key *authkey);
 extern int key_reject_and_link(struct key *key,
                               unsigned timeout,
                               unsigned error,
                               struct key *keyring,
-                              struct key *instkey);
-extern void complete_request_key(struct key_construction *cons, int error);
+                              struct key *authkey);
+extern void complete_request_key(struct key *authkey, int error);
 
 static inline int key_negate_and_link(struct key *key,
                                      unsigned timeout,
                                      struct key *keyring,
-                                     struct key *instkey)
+                                     struct key *authkey)
 {
-       return key_reject_and_link(key, timeout, ENOKEY, keyring, instkey);
+       return key_reject_and_link(key, timeout, ENOKEY, keyring, authkey);
 }
 
 extern int generic_key_instantiate(struct key *key, struct key_preparsed_payload *prep);
index 5440f11..ad60961 100644 (file)
@@ -160,6 +160,7 @@ static inline struct nd_blk_region_desc *to_blk_region_desc(
 }
 
 enum nvdimm_security_state {
+       NVDIMM_SECURITY_ERROR = -1,
        NVDIMM_SECURITY_DISABLED,
        NVDIMM_SECURITY_UNLOCKED,
        NVDIMM_SECURITY_LOCKED,
@@ -234,7 +235,6 @@ static inline struct nvdimm *nvdimm_create(struct nvdimm_bus *nvdimm_bus,
                        cmd_mask, num_flush, flush_wpq, NULL, NULL);
 }
 
-int nvdimm_security_setup_events(struct nvdimm *nvdimm);
 const struct nd_cmd_desc *nd_cmd_dimm_desc(int cmd);
 const struct nd_cmd_desc *nd_cmd_bus_desc(int cmd);
 u32 nd_cmd_in_size(struct nvdimm *nvdimm, int cmd,
index 64c41cf..859b55b 100644 (file)
@@ -29,9 +29,6 @@ extern unsigned long max_pfn;
  */
 extern unsigned long long max_possible_pfn;
 
-#define INIT_MEMBLOCK_REGIONS  128
-#define INIT_PHYSMEM_REGIONS   4
-
 /**
  * enum memblock_flags - definition of memory region attributes
  * @MEMBLOCK_NONE: no special request
index 07da5c6..368267c 100644 (file)
@@ -21,14 +21,16 @@ struct vmem_altmap;
  * walkers which rely on the fully initialized page->flags and others
  * should use this rather than pfn_valid && pfn_to_page
  */
-#define pfn_to_online_page(pfn)                                \
-({                                                     \
-       struct page *___page = NULL;                    \
-       unsigned long ___nr = pfn_to_section_nr(pfn);   \
-                                                       \
-       if (___nr < NR_MEM_SECTIONS && online_section_nr(___nr))\
-               ___page = pfn_to_page(pfn);             \
-       ___page;                                        \
+#define pfn_to_online_page(pfn)                                           \
+({                                                                \
+       struct page *___page = NULL;                               \
+       unsigned long ___pfn = pfn;                                \
+       unsigned long ___nr = pfn_to_section_nr(___pfn);           \
+                                                                  \
+       if (___nr < NR_MEM_SECTIONS && online_section_nr(___nr) && \
+           pfn_valid_within(___pfn))                              \
+               ___page = pfn_to_page(___pfn);                     \
+       ___page;                                                   \
 })
 
 /*
index 9a9631f..fc91082 100644 (file)
@@ -2790,6 +2790,100 @@ struct ec_response_battery_vendor_param {
        uint32_t value;
 } __packed;
 
+/*****************************************************************************/
+/* Commands for I2S recording on audio codec. */
+
+#define EC_CMD_CODEC_I2S 0x00BC
+
+enum ec_codec_i2s_subcmd {
+       EC_CODEC_SET_SAMPLE_DEPTH = 0x0,
+       EC_CODEC_SET_GAIN = 0x1,
+       EC_CODEC_GET_GAIN = 0x2,
+       EC_CODEC_I2S_ENABLE = 0x3,
+       EC_CODEC_I2S_SET_CONFIG = 0x4,
+       EC_CODEC_I2S_SET_TDM_CONFIG = 0x5,
+       EC_CODEC_I2S_SET_BCLK = 0x6,
+};
+
+enum ec_sample_depth_value {
+       EC_CODEC_SAMPLE_DEPTH_16 = 0,
+       EC_CODEC_SAMPLE_DEPTH_24 = 1,
+};
+
+enum ec_i2s_config {
+       EC_DAI_FMT_I2S = 0,
+       EC_DAI_FMT_RIGHT_J = 1,
+       EC_DAI_FMT_LEFT_J = 2,
+       EC_DAI_FMT_PCM_A = 3,
+       EC_DAI_FMT_PCM_B = 4,
+       EC_DAI_FMT_PCM_TDM = 5,
+};
+
+struct ec_param_codec_i2s {
+       /*
+        * enum ec_codec_i2s_subcmd
+        */
+       uint8_t cmd;
+       union {
+               /*
+                * EC_CODEC_SET_SAMPLE_DEPTH
+                * Value should be one of ec_sample_depth_value.
+                */
+               uint8_t depth;
+
+               /*
+                * EC_CODEC_SET_GAIN
+                * Value should be 0~43 for both channels.
+                */
+               struct ec_param_codec_i2s_set_gain {
+                       uint8_t left;
+                       uint8_t right;
+               } __packed gain;
+
+               /*
+                * EC_CODEC_I2S_ENABLE
+                * 1 to enable, 0 to disable.
+                */
+               uint8_t i2s_enable;
+
+               /*
+                * EC_CODEC_I2S_SET_COFNIG
+                * Value should be one of ec_i2s_config.
+                */
+               uint8_t i2s_config;
+
+               /*
+                * EC_CODEC_I2S_SET_TDM_CONFIG
+                * Value should be one of ec_i2s_config.
+                */
+               struct ec_param_codec_i2s_tdm {
+                       /*
+                        * 0 to 496
+                        */
+                       int16_t ch0_delay;
+                       /*
+                        * -1 to 496
+                        */
+                       int16_t ch1_delay;
+                       uint8_t adjacent_to_ch0;
+                       uint8_t adjacent_to_ch1;
+               } __packed tdm_param;
+
+               /*
+                * EC_CODEC_I2S_SET_BCLK
+                */
+               uint32_t bclk;
+       };
+} __packed;
+
+/*
+ * For subcommand EC_CODEC_GET_GAIN.
+ */
+struct ec_response_codec_gain {
+       uint8_t left;
+       uint8_t right;
+} __packed;
+
 /*****************************************************************************/
 /* System commands */
 
index ab16ad2..2083fa2 100644 (file)
@@ -41,7 +41,7 @@
 #define TCU_TCSR_PRESCALE_LSB          3
 #define TCU_TCSR_PRESCALE_MASK         0x38
 
-#define TCU_TCSR_PWM_SD                BIT(9)  /* 0: Shutdown abruptly 1: gracefully */
+#define TCU_TCSR_PWM_SD                BIT(9)  /* 0: Shutdown gracefully 1: abruptly */
 #define TCU_TCSR_PWM_INITL_HIGH        BIT(8)  /* Sets the initial output level */
 #define TCU_TCSR_PWM_EN                BIT(7)  /* PWM pin output enable */
 
index fe69c0f..4d5d51a 100644 (file)
@@ -15,6 +15,7 @@
 #include <linux/gpio/consumer.h>
 #include <linux/interrupt.h>
 #include <linux/mfd/madera/pdata.h>
+#include <linux/mutex.h>
 #include <linux/notifier.h>
 #include <linux/regmap.h>
 #include <linux/regulator/consumer.h>
@@ -37,6 +38,8 @@ enum madera_type {
 
 #define MADERA_MAX_MICBIAS             4
 
+#define MADERA_MAX_HP_OUTPUT           3
+
 /* Notifier events */
 #define MADERA_NOTIFY_VOICE_TRIGGER    0x1
 #define MADERA_NOTIFY_HPDET            0x2
@@ -183,6 +186,10 @@ struct madera {
        unsigned int num_childbias[MADERA_MAX_MICBIAS];
 
        struct snd_soc_dapm_context *dapm;
+       struct mutex dapm_ptr_lock;
+       unsigned int hp_ena;
+       bool out_clamp[MADERA_MAX_HP_OUTPUT];
+       bool out_shorted[MADERA_MAX_HP_OUTPUT];
 
        struct blocking_notifier_head notifier;
 };
index b9a53e0..4831684 100644 (file)
@@ -78,6 +78,8 @@
 #define STEPCONFIG_YNN         BIT(8)
 #define STEPCONFIG_XNP         BIT(9)
 #define STEPCONFIG_YPN         BIT(10)
+#define STEPCONFIG_RFP(val)    ((val) << 12)
+#define STEPCONFIG_RFP_VREFP   (0x3 << 12)
 #define STEPCONFIG_INM_MASK    (0xF << 15)
 #define STEPCONFIG_INM(val)    ((val) << 15)
 #define STEPCONFIG_INM_ADCREFM STEPCONFIG_INM(8)
@@ -86,6 +88,8 @@
 #define STEPCONFIG_INP_AN4     STEPCONFIG_INP(4)
 #define STEPCONFIG_INP_ADCREFM STEPCONFIG_INP(8)
 #define STEPCONFIG_FIFO1       BIT(26)
+#define STEPCONFIG_RFM(val)    ((val) << 23)
+#define STEPCONFIG_RFM_VREFN   (0x3 << 23)
 
 /* Delay register */
 #define STEPDELAY_OPEN_MASK    (0x3FFFF << 0)
index e2687a3..739b7bf 100644 (file)
@@ -79,7 +79,7 @@
 /* Some controllers have a CBSY bit */
 #define TMIO_MMC_HAVE_CBSY             BIT(11)
 
-/* Some controllers that support HS400 use use 4 taps while others use 8. */
+/* Some controllers that support HS400 use 4 taps while others use 8. */
 #define TMIO_MMC_HAVE_4TAP_HS400       BIT(13)
 
 int tmio_core_mmc_enable(void __iomem *cnf, int shift, unsigned long base);
index de73778..8ef3300 100644 (file)
@@ -308,6 +308,7 @@ struct mmc_card {
        unsigned int    nr_parts;
 
        unsigned int            bouncesz;       /* Bounce buffer size */
+       struct workqueue_struct *complete_wq;   /* Private workqueue */
 };
 
 static inline bool mmc_large_sector(struct mmc_card *card)
index cc4a507..842f918 100644 (file)
@@ -520,6 +520,12 @@ enum pgdat_flags {
        PGDAT_RECLAIM_LOCKED,           /* prevents concurrent reclaim */
 };
 
+enum zone_flags {
+       ZONE_BOOSTED_WATERMARK,         /* zone recently boosted watermarks.
+                                        * Cleared when kswapd is woken.
+                                        */
+};
+
 static inline unsigned long zone_managed_pages(struct zone *zone)
 {
        return (unsigned long)atomic_long_read(&zone->managed_pages);
index 9a21fe3..f5bc4c0 100644 (file)
@@ -129,13 +129,13 @@ extern void cleanup_module(void);
 #define module_init(initfn)                                    \
        static inline initcall_t __maybe_unused __inittest(void)                \
        { return initfn; }                                      \
-       int init_module(void) __attribute__((alias(#initfn)));
+       int init_module(void) __copy(initfn) __attribute__((alias(#initfn)));
 
 /* This is only required if you want to be unloadable. */
 #define module_exit(exitfn)                                    \
        static inline exitcall_t __maybe_unused __exittest(void)                \
        { return exitfn; }                                      \
-       void cleanup_module(void) __attribute__((alias(#exitfn)));
+       void cleanup_module(void) __copy(exitfn) __attribute__((alias(#exitfn)));
 
 #endif
 
@@ -828,7 +828,7 @@ static inline void module_bug_finalize(const Elf_Ehdr *hdr,
 static inline void module_bug_cleanup(struct module *mod) {}
 #endif /* CONFIG_GENERIC_BUG */
 
-#ifdef RETPOLINE
+#ifdef CONFIG_RETPOLINE
 extern bool retpoline_module_ok(bool has_retpoline);
 #else
 static inline bool retpoline_module_ok(bool has_retpoline)
index 2b2a6dc..4c76fe2 100644 (file)
@@ -11,6 +11,8 @@
 #define _LINUX_NETDEV_FEATURES_H
 
 #include <linux/types.h>
+#include <linux/bitops.h>
+#include <asm/byteorder.h>
 
 typedef u64 netdev_features_t;
 
@@ -154,8 +156,26 @@ enum {
 #define NETIF_F_HW_TLS_TX      __NETIF_F(HW_TLS_TX)
 #define NETIF_F_HW_TLS_RX      __NETIF_F(HW_TLS_RX)
 
-#define for_each_netdev_feature(mask_addr, bit)        \
-       for_each_set_bit(bit, (unsigned long *)mask_addr, NETDEV_FEATURE_COUNT)
+/* Finds the next feature with the highest number of the range of start till 0.
+ */
+static inline int find_next_netdev_feature(u64 feature, unsigned long start)
+{
+       /* like BITMAP_LAST_WORD_MASK() for u64
+        * this sets the most significant 64 - start to 0.
+        */
+       feature &= ~0ULL >> (-start & ((sizeof(feature) * 8) - 1));
+
+       return fls64(feature) - 1;
+}
+
+/* This goes for the MSB to the LSB through the set feature bits,
+ * mask_addr should be a u64 and bit an int
+ */
+#define for_each_netdev_feature(mask_addr, bit)                                \
+       for ((bit) = find_next_netdev_feature((mask_addr),              \
+                                             NETDEV_FEATURE_COUNT);    \
+            (bit) >= 0;                                                \
+            (bit) = find_next_netdev_feature((mask_addr), (bit) - 1))
 
 /* Features valid for ethtool to change */
 /* = all defined minus driver/device-class-related */
index 1377d08..86dbb3e 100644 (file)
@@ -1483,6 +1483,7 @@ struct net_device_ops {
  * @IFF_NO_RX_HANDLER: device doesn't support the rx_handler hook
  * @IFF_FAILOVER: device is a failover master device
  * @IFF_FAILOVER_SLAVE: device is lower dev of a failover master device
+ * @IFF_L3MDEV_RX_HANDLER: only invoke the rx handler of L3 master device
  */
 enum netdev_priv_flags {
        IFF_802_1Q_VLAN                 = 1<<0,
@@ -1514,6 +1515,7 @@ enum netdev_priv_flags {
        IFF_NO_RX_HANDLER               = 1<<26,
        IFF_FAILOVER                    = 1<<27,
        IFF_FAILOVER_SLAVE              = 1<<28,
+       IFF_L3MDEV_RX_HANDLER           = 1<<29,
 };
 
 #define IFF_802_1Q_VLAN                        IFF_802_1Q_VLAN
@@ -1544,6 +1546,7 @@ enum netdev_priv_flags {
 #define IFF_NO_RX_HANDLER              IFF_NO_RX_HANDLER
 #define IFF_FAILOVER                   IFF_FAILOVER
 #define IFF_FAILOVER_SLAVE             IFF_FAILOVER_SLAVE
+#define IFF_L3MDEV_RX_HANDLER          IFF_L3MDEV_RX_HANDLER
 
 /**
  *     struct net_device - The DEVICE structure.
@@ -4549,6 +4552,11 @@ static inline bool netif_supports_nofcs(struct net_device *dev)
        return dev->priv_flags & IFF_SUPP_NOFCS;
 }
 
+static inline bool netif_has_l3_rx_handler(const struct net_device *dev)
+{
+       return dev->priv_flags & IFF_L3MDEV_RX_HANDLER;
+}
+
 static inline bool netif_is_l3_master(const struct net_device *dev)
 {
        return dev->priv_flags & IFF_L3MDEV_MASTER;
index fe472e5..e240992 100644 (file)
@@ -50,7 +50,6 @@ struct of_irq_controller;
 
 struct device_node {
        const char *name;
-       const char *type;
        phandle phandle;
        const char *full_name;
        struct fwnode_handle fwnode;
index cb1adf0..249d4d7 100644 (file)
@@ -24,7 +24,7 @@ static inline void *
 pci_zalloc_consistent(struct pci_dev *hwdev, size_t size,
                      dma_addr_t *dma_handle)
 {
-       return dma_zalloc_coherent(&hwdev->dev, size, dma_handle, GFP_ATOMIC);
+       return dma_alloc_coherent(&hwdev->dev, size, dma_handle, GFP_ATOMIC);
 }
 
 static inline void
index 1d5c551..e1a0517 100644 (file)
@@ -447,6 +447,11 @@ struct pmu {
         * Filter events for PMU-specific reasons.
         */
        int (*filter_match)             (struct perf_event *event); /* optional */
+
+       /*
+        * Check period value for PERF_EVENT_IOC_PERIOD ioctl.
+        */
+       int (*check_period)             (struct perf_event *event, u64 value); /* optional */
 };
 
 enum perf_addr_filter_action_t {
index 3b051f7..333b56d 100644 (file)
@@ -48,6 +48,7 @@ extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_features) __ro_after_init;
 extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_fibre_features) __ro_after_init;
 extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_gbit_all_ports_features) __ro_after_init;
 extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_features) __ro_after_init;
+extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_fec_features) __ro_after_init;
 extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_init;
 
 #define PHY_BASIC_FEATURES ((unsigned long *)&phy_basic_features)
@@ -56,6 +57,7 @@ extern __ETHTOOL_DECLARE_LINK_MODE_MASK(phy_10gbit_full_features) __ro_after_ini
 #define PHY_GBIT_FIBRE_FEATURES ((unsigned long *)&phy_gbit_fibre_features)
 #define PHY_GBIT_ALL_PORTS_FEATURES ((unsigned long *)&phy_gbit_all_ports_features)
 #define PHY_10GBIT_FEATURES ((unsigned long *)&phy_10gbit_features)
+#define PHY_10GBIT_FEC_FEATURES ((unsigned long *)&phy_10gbit_fec_features)
 #define PHY_10GBIT_FULL_FEATURES ((unsigned long *)&phy_10gbit_full_features)
 
 extern const int phy_10_100_features_array[4];
@@ -467,8 +469,8 @@ struct phy_device {
  *   only works for PHYs with IDs which match this field
  * name: The friendly name of this PHY type
  * phy_id_mask: Defines the important bits of the phy_id
- * features: A list of features (speed, duplex, etc) supported
- *   by this PHY
+ * features: A mandatory list of features (speed, duplex, etc)
+ *   supported by this PHY
  * flags: A bitfield defining certain other features this PHY
  *   supports (like interrupts)
  *
@@ -672,26 +674,13 @@ phy_lookup_setting(int speed, int duplex, const unsigned long *mask,
 size_t phy_speeds(unsigned int *speeds, size_t size,
                  unsigned long *mask);
 
-static inline bool __phy_is_started(struct phy_device *phydev)
-{
-       WARN_ON(!mutex_is_locked(&phydev->lock));
-
-       return phydev->state >= PHY_UP;
-}
-
 /**
  * phy_is_started - Convenience function to check whether PHY is started
  * @phydev: The phy_device struct
  */
 static inline bool phy_is_started(struct phy_device *phydev)
 {
-       bool started;
-
-       mutex_lock(&phydev->lock);
-       started = __phy_is_started(phydev);
-       mutex_unlock(&phydev->lock);
-
-       return started;
+       return phydev->state >= PHY_UP;
 }
 
 void phy_resolve_aneg_linkmode(struct phy_device *phydev);
@@ -1003,6 +992,14 @@ static inline int genphy_no_soft_reset(struct phy_device *phydev)
 {
        return 0;
 }
+static inline int genphy_no_ack_interrupt(struct phy_device *phydev)
+{
+       return 0;
+}
+static inline int genphy_no_config_intr(struct phy_device *phydev)
+{
+       return 0;
+}
 int genphy_read_mmd_unsupported(struct phy_device *phdev, int devad,
                                u16 regnum);
 int genphy_write_mmd_unsupported(struct phy_device *phdev, int devnum,
index e8e118d..3f350e2 100644 (file)
@@ -42,6 +42,7 @@ enum phy_mode {
        PHY_MODE_PCIE,
        PHY_MODE_ETHERNET,
        PHY_MODE_MIPI_DPHY,
+       PHY_MODE_SATA
 };
 
 /**
diff --git a/include/linux/platform_data/clk-lpss.h b/include/linux/platform_data/clk-lpss.h
deleted file mode 100644 (file)
index 2390199..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * Intel Low Power Subsystem clocks.
- *
- * Copyright (C) 2013, Intel Corporation
- * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
- *          Rafael J. Wysocki <rafael.j.wysocki@intel.com>
- *
- * This program is free software; you can redistribute it and/or modify
- * it under the terms of the GNU General Public License version 2 as
- * published by the Free Software Foundation.
- */
-
-#ifndef __CLK_LPSS_H
-#define __CLK_LPSS_H
-
-struct lpss_clk_data {
-       const char *name;
-       struct clk *clk;
-};
-
-extern int lpt_clk_init(void);
-
-#endif /* __CLK_LPSS_H */
diff --git a/include/linux/platform_data/x86/clk-lpss.h b/include/linux/platform_data/x86/clk-lpss.h
new file mode 100644 (file)
index 0000000..2390199
--- /dev/null
@@ -0,0 +1,23 @@
+/*
+ * Intel Low Power Subsystem clocks.
+ *
+ * Copyright (C) 2013, Intel Corporation
+ * Authors: Mika Westerberg <mika.westerberg@linux.intel.com>
+ *          Rafael J. Wysocki <rafael.j.wysocki@intel.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ */
+
+#ifndef __CLK_LPSS_H
+#define __CLK_LPSS_H
+
+struct lpss_clk_data {
+       const char *name;
+       struct clk *clk;
+};
+
+extern int lpt_clk_init(void);
+
+#endif /* __CLK_LPSS_H */
index 0a2a88e..b895f4e 100644 (file)
@@ -108,6 +108,7 @@ void dev_pm_opp_put(struct dev_pm_opp *opp);
 int dev_pm_opp_add(struct device *dev, unsigned long freq,
                   unsigned long u_volt);
 void dev_pm_opp_remove(struct device *dev, unsigned long freq);
+void dev_pm_opp_remove_all_dynamic(struct device *dev);
 
 int dev_pm_opp_enable(struct device *dev, unsigned long freq);
 
@@ -217,6 +218,10 @@ static inline void dev_pm_opp_remove(struct device *dev, unsigned long freq)
 {
 }
 
+static inline void dev_pm_opp_remove_all_dynamic(struct device *dev)
+{
+}
+
 static inline int dev_pm_opp_enable(struct device *dev, unsigned long freq)
 {
        return 0;
index 54af4ee..fed5be7 100644 (file)
@@ -105,7 +105,7 @@ static inline bool pm_runtime_callbacks_present(struct device *dev)
 
 static inline void pm_runtime_mark_last_busy(struct device *dev)
 {
-       WRITE_ONCE(dev->power.last_busy, ktime_to_ns(ktime_get()));
+       WRITE_ONCE(dev->power.last_busy, ktime_get_mono_fast_ns());
 }
 
 static inline bool pm_runtime_is_irq_safe(struct device *dev)
index 1637385..d0aecc0 100644 (file)
@@ -13,6 +13,7 @@
 #ifndef __QCOM_SCM_H
 #define __QCOM_SCM_H
 
+#include <linux/err.h>
 #include <linux/types.h>
 #include <linux/cpumask.h>
 
index 59ddf9a..2dd0a9e 100644 (file)
@@ -663,6 +663,37 @@ out:
 static inline void qed_chain_set_prod(struct qed_chain *p_chain,
                                      u32 prod_idx, void *p_prod_elem)
 {
+       if (p_chain->mode == QED_CHAIN_MODE_PBL) {
+               u32 cur_prod, page_mask, page_cnt, page_diff;
+
+               cur_prod = is_chain_u16(p_chain) ? p_chain->u.chain16.prod_idx :
+                          p_chain->u.chain32.prod_idx;
+
+               /* Assume that number of elements in a page is power of 2 */
+               page_mask = ~p_chain->elem_per_page_mask;
+
+               /* Use "cur_prod - 1" and "prod_idx - 1" since producer index
+                * reaches the first element of next page before the page index
+                * is incremented. See qed_chain_produce().
+                * Index wrap around is not a problem because the difference
+                * between current and given producer indices is always
+                * positive and lower than the chain's capacity.
+                */
+               page_diff = (((cur_prod - 1) & page_mask) -
+                            ((prod_idx - 1) & page_mask)) /
+                           p_chain->elem_per_page;
+
+               page_cnt = qed_chain_get_page_cnt(p_chain);
+               if (is_chain_u16(p_chain))
+                       p_chain->pbl.c.u16.prod_page_idx =
+                               (p_chain->pbl.c.u16.prod_page_idx -
+                                page_diff + page_cnt) % page_cnt;
+               else
+                       p_chain->pbl.c.u32.prod_page_idx =
+                               (p_chain->pbl.c.u32.prod_page_idx -
+                                page_diff + page_cnt) % page_cnt;
+       }
+
        if (is_chain_u16(p_chain))
                p_chain->u.chain16.prod_idx = (u16) prod_idx;
        else
index 29af6d6..c1901b6 100644 (file)
@@ -32,6 +32,8 @@ struct reset_control *devm_reset_control_array_get(struct device *dev,
 struct reset_control *of_reset_control_array_get(struct device_node *np,
                                                 bool shared, bool optional);
 
+int reset_control_get_count(struct device *dev);
+
 #else
 
 static inline int reset_control_reset(struct reset_control *rstc)
@@ -97,6 +99,11 @@ of_reset_control_array_get(struct device_node *np, bool shared, bool optional)
        return optional ? NULL : ERR_PTR(-ENOTSUPP);
 }
 
+static inline int reset_control_get_count(struct device *dev)
+{
+       return -ENOENT;
+}
+
 #endif /* CONFIG_RESET_CONTROLLER */
 
 static inline int __must_check device_reset(struct device *dev)
@@ -138,7 +145,7 @@ __must_check reset_control_get_exclusive(struct device *dev, const char *id)
  *
  * Returns a struct reset_control or IS_ERR() condition containing errno.
  * This function is intended for use with reset-controls which are shared
- * between hardware-blocks.
+ * between hardware blocks.
  *
  * When a reset-control is shared, the behavior of reset_control_assert /
  * deassert is changed, the reset-core will keep track of a deassert_count
@@ -187,7 +194,7 @@ static inline struct reset_control *of_reset_control_get_exclusive(
 }
 
 /**
- * of_reset_control_get_shared - Lookup and obtain an shared reference
+ * of_reset_control_get_shared - Lookup and obtain a shared reference
  *                               to a reset controller.
  * @node: device to be reset by the controller
  * @id: reset line name
@@ -229,7 +236,7 @@ static inline struct reset_control *of_reset_control_get_exclusive_by_index(
 }
 
 /**
- * of_reset_control_get_shared_by_index - Lookup and obtain an shared
+ * of_reset_control_get_shared_by_index - Lookup and obtain a shared
  *                                        reference to a reset controller
  *                                        by index.
  * @node: device to be reset by the controller
@@ -322,7 +329,7 @@ devm_reset_control_get_exclusive_by_index(struct device *dev, int index)
 
 /**
  * devm_reset_control_get_shared_by_index - resource managed
- * reset_control_get_shared
+ *                                          reset_control_get_shared
  * @dev: device to be reset by the controller
  * @index: index of the reset controller
  *
index 89541d2..bba3afb 100644 (file)
@@ -995,7 +995,7 @@ struct task_struct {
        /* cg_list protected by css_set_lock and tsk->alloc_lock: */
        struct list_head                cg_list;
 #endif
-#ifdef CONFIG_RESCTRL
+#ifdef CONFIG_X86_CPU_RESCTRL
        u32                             closid;
        u32                             rmid;
 #endif
@@ -1406,6 +1406,7 @@ extern struct pid *cad_pid;
 #define PF_RANDOMIZE           0x00400000      /* Randomize virtual address space */
 #define PF_SWAPWRITE           0x00800000      /* Allowed to write to swap */
 #define PF_MEMSTALL            0x01000000      /* Stalled due to lack of memory */
+#define PF_UMH                 0x02000000      /* I'm an Usermodehelper process */
 #define PF_NO_SETAFFINITY      0x04000000      /* Userland is not allowed to meddle with cpus_allowed */
 #define PF_MCE_EARLY           0x08000000      /* Early kill for mce process policy */
 #define PF_MUTEX_TESTER                0x20000000      /* Thread belongs to the rt mutex tester */
@@ -1904,6 +1905,14 @@ static inline void rseq_execve(struct task_struct *t)
 
 #endif
 
+void __exit_umh(struct task_struct *tsk);
+
+static inline void exit_umh(struct task_struct *tsk)
+{
+       if (unlikely(tsk->flags & PF_UMH))
+               __exit_umh(tsk);
+}
+
 #ifdef CONFIG_DEBUG_RSEQ
 
 void rseq_syscall(struct pt_regs *regs);
index ec912d0..ecdc654 100644 (file)
@@ -71,6 +71,7 @@ static inline int get_dumpable(struct mm_struct *mm)
 #define MMF_HUGE_ZERO_PAGE     23      /* mm has ever used the global huge zero page */
 #define MMF_DISABLE_THP                24      /* disable THP for all VMAs */
 #define MMF_OOM_VICTIM         25      /* mm is the oom victim */
+#define MMF_OOM_REAP_QUEUED    26      /* mm was queued for oom_reaper */
 #define MMF_DISABLE_THP_MASK   (1 << MMF_DISABLE_THP)
 
 #define MMF_INIT_MASK          (MMF_DUMPABLE_MASK | MMF_DUMP_FILTER_MASK |\
index 10b19a1..545f371 100644 (file)
  * called near the end of a function. Otherwise, the list can be
  * re-initialized for later re-use by wake_q_init().
  *
- * Note that this can cause spurious wakeups. schedule() callers
+ * NOTE that this can cause spurious wakeups. schedule() callers
  * must ensure the call is done inside a loop, confirming that the
  * wakeup condition has in fact occurred.
+ *
+ * NOTE that there is no guarantee the wakeup will happen any later than the
+ * wake_q_add() location. Therefore task must be ready to be woken at the
+ * location of the wake_q_add().
  */
 
 #include <linux/sched.h>
index cc7e2c1..9702016 100644 (file)
@@ -392,7 +392,7 @@ extern bool unhandled_signal(struct task_struct *tsk, int sig);
 #endif
 
 #define siginmask(sig, mask) \
-       ((sig) < SIGRTMIN && (rt_sigmask(sig) & (mask)))
+       ((sig) > 0 && (sig) < SIGRTMIN && (rt_sigmask(sig) & (mask)))
 
 #define SIG_KERNEL_ONLY_MASK (\
        rt_sigmask(SIGKILL)   |  rt_sigmask(SIGSTOP))
index 93f56fd..bdb9563 100644 (file)
@@ -2434,7 +2434,7 @@ static inline void skb_probe_transport_header(struct sk_buff *skb,
 
        if (skb_flow_dissect_flow_keys_basic(skb, &keys, NULL, 0, 0, 0, 0))
                skb_set_transport_header(skb, keys.control.thoff);
-       else
+       else if (offset_hint >= 0)
                skb_set_transport_header(skb, offset_hint);
 }
 
@@ -3218,6 +3218,7 @@ int pskb_trim_rcsum_slow(struct sk_buff *skb, unsigned int len);
  *
  *     This is exactly the same as pskb_trim except that it ensures the
  *     checksum of received packets are still valid after the operation.
+ *     It can change skb pointers.
  */
 
 static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
@@ -4211,6 +4212,12 @@ static inline bool skb_is_gso_sctp(const struct sk_buff *skb)
        return skb_shinfo(skb)->gso_type & SKB_GSO_SCTP;
 }
 
+static inline bool skb_is_gso_tcp(const struct sk_buff *skb)
+{
+       return skb_is_gso(skb) &&
+              skb_shinfo(skb)->gso_type & (SKB_GSO_TCPV4 | SKB_GSO_TCPV6);
+}
+
 static inline void skb_gso_reset(struct sk_buff *skb)
 {
        skb_shinfo(skb)->gso_size = 0;
index 7ddfc65..4335bd7 100644 (file)
@@ -184,6 +184,7 @@ struct plat_stmmacenet_data {
        struct clk *pclk;
        struct clk *clk_ptp_ref;
        unsigned int clk_ptp_rate;
+       unsigned int clk_ref_rate;
        struct reset_control *stmmac_rst;
        struct stmmac_axi *axi;
        int has_gmac4;
index 235f51b..0c08de3 100644 (file)
@@ -47,6 +47,8 @@ struct umh_info {
        const char *cmdline;
        struct file *pipe_to_umh;
        struct file *pipe_from_umh;
+       struct list_head list;
+       void (*cleanup)(struct umh_info *info);
        pid_t pid;
 };
 int fork_usermode_blob(void *data, size_t len, struct umh_info *info);
index 32baf8e..987b649 100644 (file)
@@ -12,6 +12,11 @@ struct irq_affinity;
 
 /**
  * virtio_config_ops - operations for configuring a virtio device
+ * Note: Do not assume that a transport implements all of the operations
+ *       getting/setting a value as a simple read/write! Generally speaking,
+ *       any of @get/@set, @get_status/@set_status, or @get_features/
+ *       @finalize_features are NOT safe to be called from an atomic
+ *       context.
  * @get: read the value of a configuration field
  *     vdev: the virtio_device
  *     offset: the offset of the configuration field
@@ -22,7 +27,7 @@ struct irq_affinity;
  *     offset: the offset of the configuration field
  *     buf: the buffer to read the field value from.
  *     len: the length of the buffer
- * @generation: config generation counter
+ * @generation: config generation counter (optional)
  *     vdev: the virtio_device
  *     Returns the config generation counter
  * @get_status: read the status byte
@@ -48,17 +53,17 @@ struct irq_affinity;
  * @del_vqs: free virtqueues found by find_vqs().
  * @get_features: get the array of feature bits for this device.
  *     vdev: the virtio_device
- *     Returns the first 32 feature bits (all we currently need).
+ *     Returns the first 64 feature bits (all we currently need).
  * @finalize_features: confirm what device features we'll be using.
  *     vdev: the virtio_device
  *     This gives the final feature bits for the device: it can change
  *     the dev->feature bits if it wants.
  *     Returns 0 on success or error status
- * @bus_name: return the bus name associated with the device
+ * @bus_name: return the bus name associated with the device (optional)
  *     vdev: the virtio_device
  *      This returns a pointer to the bus name a la pci_name from which
  *      the caller can then copy.
- * @set_vq_affinity: set the affinity for a virtqueue.
+ * @set_vq_affinity: set the affinity for a virtqueue (optional).
  * @get_vq_affinity: get the affinity for a virtqueue (optional).
  */
 typedef void vq_callback_t(struct virtqueue *);
index cb462f9..e0348cb 100644 (file)
@@ -57,6 +57,25 @@ static inline int virtio_net_hdr_to_skb(struct sk_buff *skb,
 
                if (!skb_partial_csum_set(skb, start, off))
                        return -EINVAL;
+       } else {
+               /* gso packets without NEEDS_CSUM do not set transport_offset.
+                * probe and drop if does not match one of the above types.
+                */
+               if (gso_type && skb->network_header) {
+                       if (!skb->protocol)
+                               virtio_net_hdr_set_proto(skb, hdr);
+retry:
+                       skb_probe_transport_header(skb, -1);
+                       if (!skb_transport_header_was_set(skb)) {
+                               /* UFO does not specify ipv4 or 6: try both */
+                               if (gso_type & SKB_GSO_UDP &&
+                                   skb->protocol == htons(ETH_P_IP)) {
+                                       skb->protocol = htons(ETH_P_IPV6);
+                                       goto retry;
+                               }
+                               return -EINVAL;
+                       }
+               }
        }
 
        if (hdr->gso_type != VIRTIO_NET_HDR_GSO_NONE) {
index f492e21..5d9d318 100644 (file)
@@ -176,7 +176,8 @@ static inline bool xa_is_internal(const void *entry)
  */
 static inline bool xa_is_err(const void *entry)
 {
-       return unlikely(xa_is_internal(entry));
+       return unlikely(xa_is_internal(entry) &&
+                       entry >= xa_mk_internal(-MAX_ERRNO));
 }
 
 /**
@@ -286,7 +287,6 @@ struct xarray {
  */
 #define DEFINE_XARRAY_ALLOC(name) DEFINE_XARRAY_FLAGS(name, XA_FLAGS_ALLOC)
 
-void xa_init_flags(struct xarray *, gfp_t flags);
 void *xa_load(struct xarray *, unsigned long index);
 void *xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);
 void *xa_erase(struct xarray *, unsigned long index);
@@ -303,6 +303,24 @@ unsigned int xa_extract(struct xarray *, void **dst, unsigned long start,
                unsigned long max, unsigned int n, xa_mark_t);
 void xa_destroy(struct xarray *);
 
+/**
+ * xa_init_flags() - Initialise an empty XArray with flags.
+ * @xa: XArray.
+ * @flags: XA_FLAG values.
+ *
+ * If you need to initialise an XArray with special flags (eg you need
+ * to take the lock from interrupt context), use this function instead
+ * of xa_init().
+ *
+ * Context: Any context.
+ */
+static inline void xa_init_flags(struct xarray *xa, gfp_t flags)
+{
+       spin_lock_init(&xa->xa_lock);
+       xa->xa_flags = flags;
+       xa->xa_head = NULL;
+}
+
 /**
  * xa_init() - Initialise an empty XArray.
  * @xa: XArray.
@@ -342,20 +360,45 @@ static inline bool xa_marked(const struct xarray *xa, xa_mark_t mark)
 }
 
 /**
- * xa_for_each() - Iterate over a portion of an XArray.
+ * xa_for_each_start() - Iterate over a portion of an XArray.
  * @xa: XArray.
+ * @index: Index of @entry.
  * @entry: Entry retrieved from array.
+ * @start: First index to retrieve from array.
+ *
+ * During the iteration, @entry will have the value of the entry stored
+ * in @xa at @index.  You may modify @index during the iteration if you
+ * want to skip or reprocess indices.  It is safe to modify the array
+ * during the iteration.  At the end of the iteration, @entry will be set
+ * to NULL and @index will have a value less than or equal to max.
+ *
+ * xa_for_each_start() is O(n.log(n)) while xas_for_each() is O(n).  You have
+ * to handle your own locking with xas_for_each(), and if you have to unlock
+ * after each iteration, it will also end up being O(n.log(n)).
+ * xa_for_each_start() will spin if it hits a retry entry; if you intend to
+ * see retry entries, you should use the xas_for_each() iterator instead.
+ * The xas_for_each() iterator will expand into more inline code than
+ * xa_for_each_start().
+ *
+ * Context: Any context.  Takes and releases the RCU lock.
+ */
+#define xa_for_each_start(xa, index, entry, start)                     \
+       for (index = start,                                             \
+            entry = xa_find(xa, &index, ULONG_MAX, XA_PRESENT);        \
+            entry;                                                     \
+            entry = xa_find_after(xa, &index, ULONG_MAX, XA_PRESENT))
+
+/**
+ * xa_for_each() - Iterate over present entries in an XArray.
+ * @xa: XArray.
  * @index: Index of @entry.
- * @max: Maximum index to retrieve from array.
- * @filter: Selection criterion.
+ * @entry: Entry retrieved from array.
  *
- * Initialise @index to the lowest index you want to retrieve from the
- * array.  During the iteration, @entry will have the value of the entry
- * stored in @xa at @index.  The iteration will skip all entries in the
- * array which do not match @filter.  You may modify @index during the
- * iteration if you want to skip or reprocess indices.  It is safe to modify
- * the array during the iteration.  At the end of the iteration, @entry will
- * be set to NULL and @index will have a value less than or equal to max.
+ * During the iteration, @entry will have the value of the entry stored
+ * in @xa at @index.  You may modify @index during the iteration if you want
+ * to skip or reprocess indices.  It is safe to modify the array during the
+ * iteration.  At the end of the iteration, @entry will be set to NULL and
+ * @index will have a value less than or equal to max.
  *
  * xa_for_each() is O(n.log(n)) while xas_for_each() is O(n).  You have
  * to handle your own locking with xas_for_each(), and if you have to unlock
@@ -366,9 +409,36 @@ static inline bool xa_marked(const struct xarray *xa, xa_mark_t mark)
  *
  * Context: Any context.  Takes and releases the RCU lock.
  */
-#define xa_for_each(xa, entry, index, max, filter) \
-       for (entry = xa_find(xa, &index, max, filter); entry; \
-            entry = xa_find_after(xa, &index, max, filter))
+#define xa_for_each(xa, index, entry) \
+       xa_for_each_start(xa, index, entry, 0)
+
+/**
+ * xa_for_each_marked() - Iterate over marked entries in an XArray.
+ * @xa: XArray.
+ * @index: Index of @entry.
+ * @entry: Entry retrieved from array.
+ * @filter: Selection criterion.
+ *
+ * During the iteration, @entry will have the value of the entry stored
+ * in @xa at @index.  The iteration will skip all entries in the array
+ * which do not match @filter.  You may modify @index during the iteration
+ * if you want to skip or reprocess indices.  It is safe to modify the array
+ * during the iteration.  At the end of the iteration, @entry will be set to
+ * NULL and @index will have a value less than or equal to max.
+ *
+ * xa_for_each_marked() is O(n.log(n)) while xas_for_each_marked() is O(n).
+ * You have to handle your own locking with xas_for_each(), and if you have
+ * to unlock after each iteration, it will also end up being O(n.log(n)).
+ * xa_for_each_marked() will spin if it hits a retry entry; if you intend to
+ * see retry entries, you should use the xas_for_each_marked() iterator
+ * instead.  The xas_for_each_marked() iterator will expand into more inline
+ * code than xa_for_each_marked().
+ *
+ * Context: Any context.  Takes and releases the RCU lock.
+ */
+#define xa_for_each_marked(xa, index, entry, filter) \
+       for (index = 0, entry = xa_find(xa, &index, ULONG_MAX, filter); \
+            entry; entry = xa_find_after(xa, &index, ULONG_MAX, filter))
 
 #define xa_trylock(xa)         spin_trylock(&(xa)->xa_lock)
 #define xa_lock(xa)            spin_lock(&(xa)->xa_lock)
@@ -393,39 +463,12 @@ void *__xa_erase(struct xarray *, unsigned long index);
 void *__xa_store(struct xarray *, unsigned long index, void *entry, gfp_t);
 void *__xa_cmpxchg(struct xarray *, unsigned long index, void *old,
                void *entry, gfp_t);
+int __xa_insert(struct xarray *, unsigned long index, void *entry, gfp_t);
 int __xa_alloc(struct xarray *, u32 *id, u32 max, void *entry, gfp_t);
 int __xa_reserve(struct xarray *, unsigned long index, gfp_t);
 void __xa_set_mark(struct xarray *, unsigned long index, xa_mark_t);
 void __xa_clear_mark(struct xarray *, unsigned long index, xa_mark_t);
 
-/**
- * __xa_insert() - Store this entry in the XArray unless another entry is
- *                     already present.
- * @xa: XArray.
- * @index: Index into array.
- * @entry: New entry.
- * @gfp: Memory allocation flags.
- *
- * If you would rather see the existing entry in the array, use __xa_cmpxchg().
- * This function is for users who don't care what the entry is, only that
- * one is present.
- *
- * Context: Any context.  Expects xa_lock to be held on entry.  May
- *         release and reacquire xa_lock if the @gfp flags permit.
- * Return: 0 if the store succeeded.  -EEXIST if another entry was present.
- * -ENOMEM if memory could not be allocated.
- */
-static inline int __xa_insert(struct xarray *xa, unsigned long index,
-               void *entry, gfp_t gfp)
-{
-       void *curr = __xa_cmpxchg(xa, index, NULL, entry, gfp);
-       if (!curr)
-               return 0;
-       if (xa_is_err(curr))
-               return xa_err(curr);
-       return -EEXIST;
-}
-
 /**
  * xa_store_bh() - Store this entry in the XArray.
  * @xa: XArray.
@@ -453,7 +496,7 @@ static inline void *xa_store_bh(struct xarray *xa, unsigned long index,
 }
 
 /**
- * xa_store_irq() - Erase this entry from the XArray.
+ * xa_store_irq() - Store this entry in the XArray.
  * @xa: XArray.
  * @index: Index into array.
  * @entry: New entry.
@@ -615,24 +658,83 @@ static inline void *xa_cmpxchg_irq(struct xarray *xa, unsigned long index,
  * @entry: New entry.
  * @gfp: Memory allocation flags.
  *
- * If you would rather see the existing entry in the array, use xa_cmpxchg().
- * This function is for users who don't care what the entry is, only that
- * one is present.
+ * Inserting a NULL entry will store a reserved entry (like xa_reserve())
+ * if no entry is present.  Inserting will fail if a reserved entry is
+ * present, even though loading from this index will return NULL.
  *
- * Context: Process context.  Takes and releases the xa_lock.
- *         May sleep if the @gfp flags permit.
+ * Context: Any context.  Takes and releases the xa_lock.  May sleep if
+ * the @gfp flags permit.
  * Return: 0 if the store succeeded.  -EEXIST if another entry was present.
  * -ENOMEM if memory could not be allocated.
  */
 static inline int xa_insert(struct xarray *xa, unsigned long index,
                void *entry, gfp_t gfp)
 {
-       void *curr = xa_cmpxchg(xa, index, NULL, entry, gfp);
-       if (!curr)
-               return 0;
-       if (xa_is_err(curr))
-               return xa_err(curr);
-       return -EEXIST;
+       int err;
+
+       xa_lock(xa);
+       err = __xa_insert(xa, index, entry, gfp);
+       xa_unlock(xa);
+
+       return err;
+}
+
+/**
+ * xa_insert_bh() - Store this entry in the XArray unless another entry is
+ *                     already present.
+ * @xa: XArray.
+ * @index: Index into array.
+ * @entry: New entry.
+ * @gfp: Memory allocation flags.
+ *
+ * Inserting a NULL entry will store a reserved entry (like xa_reserve())
+ * if no entry is present.  Inserting will fail if a reserved entry is
+ * present, even though loading from this index will return NULL.
+ *
+ * Context: Any context.  Takes and releases the xa_lock while
+ * disabling softirqs.  May sleep if the @gfp flags permit.
+ * Return: 0 if the store succeeded.  -EEXIST if another entry was present.
+ * -ENOMEM if memory could not be allocated.
+ */
+static inline int xa_insert_bh(struct xarray *xa, unsigned long index,
+               void *entry, gfp_t gfp)
+{
+       int err;
+
+       xa_lock_bh(xa);
+       err = __xa_insert(xa, index, entry, gfp);
+       xa_unlock_bh(xa);
+
+       return err;
+}
+
+/**
+ * xa_insert_irq() - Store this entry in the XArray unless another entry is
+ *                     already present.
+ * @xa: XArray.
+ * @index: Index into array.
+ * @entry: New entry.
+ * @gfp: Memory allocation flags.
+ *
+ * Inserting a NULL entry will store a reserved entry (like xa_reserve())
+ * if no entry is present.  Inserting will fail if a reserved entry is
+ * present, even though loading from this index will return NULL.
+ *
+ * Context: Process context.  Takes and releases the xa_lock while
+ * disabling interrupts.  May sleep if the @gfp flags permit.
+ * Return: 0 if the store succeeded.  -EEXIST if another entry was present.
+ * -ENOMEM if memory could not be allocated.
+ */
+static inline int xa_insert_irq(struct xarray *xa, unsigned long index,
+               void *entry, gfp_t gfp)
+{
+       int err;
+
+       xa_lock_irq(xa);
+       err = __xa_insert(xa, index, entry, gfp);
+       xa_unlock_irq(xa);
+
+       return err;
 }
 
 /**
@@ -970,8 +1072,8 @@ static inline bool xa_is_sibling(const void *entry)
                (entry < xa_mk_sibling(XA_CHUNK_SIZE - 1));
 }
 
-#define XA_ZERO_ENTRY          xa_mk_internal(256)
-#define XA_RETRY_ENTRY         xa_mk_internal(257)
+#define XA_RETRY_ENTRY         xa_mk_internal(256)
+#define XA_ZERO_ENTRY          xa_mk_internal(257)
 
 /**
  * xa_is_zero() - Is the entry a zero entry?
@@ -995,6 +1097,17 @@ static inline bool xa_is_retry(const void *entry)
        return unlikely(entry == XA_RETRY_ENTRY);
 }
 
+/**
+ * xa_is_advanced() - Is the entry only permitted for the advanced API?
+ * @entry: Entry to be stored in the XArray.
+ *
+ * Return: %true if the entry cannot be stored by the normal API.
+ */
+static inline bool xa_is_advanced(const void *entry)
+{
+       return xa_is_internal(entry) && (entry <= XA_RETRY_ENTRY);
+}
+
 /**
  * typedef xa_update_node_t - A callback function from the XArray.
  * @node: The node which is being processed
index 1adefe4..2bfb87e 100644 (file)
@@ -20,18 +20,6 @@ struct sock;
 struct socket;
 struct rxrpc_call;
 
-/*
- * Call completion condition (state == RXRPC_CALL_COMPLETE).
- */
-enum rxrpc_call_completion {
-       RXRPC_CALL_SUCCEEDED,           /* - Normal termination */
-       RXRPC_CALL_REMOTELY_ABORTED,    /* - call aborted by peer */
-       RXRPC_CALL_LOCALLY_ABORTED,     /* - call aborted locally on error or close */
-       RXRPC_CALL_LOCAL_ERROR,         /* - call failed due to local error */
-       RXRPC_CALL_NETWORK_ERROR,       /* - call terminated by network error */
-       NR__RXRPC_CALL_COMPLETIONS
-};
-
 /*
  * Debug ID counter for tracing.
  */
@@ -73,10 +61,6 @@ int rxrpc_kernel_charge_accept(struct socket *, rxrpc_notify_rx_t,
                               rxrpc_user_attach_call_t, unsigned long, gfp_t,
                               unsigned int);
 void rxrpc_kernel_set_tx_length(struct socket *, struct rxrpc_call *, s64);
-int rxrpc_kernel_retry_call(struct socket *, struct rxrpc_call *,
-                           struct sockaddr_rxrpc *, struct key *);
-int rxrpc_kernel_check_call(struct socket *, struct rxrpc_call *,
-                           enum rxrpc_call_completion *, u32 *);
 u32 rxrpc_kernel_check_life(const struct socket *, const struct rxrpc_call *);
 void rxrpc_kernel_probe_life(struct socket *, struct rxrpc_call *);
 u32 rxrpc_kernel_get_epoch(struct socket *, struct rxrpc_call *);
index 3f9aea8..8b7eb46 100644 (file)
@@ -201,6 +201,18 @@ static inline void ax25_hold_route(ax25_route *ax25_rt)
 
 void __ax25_put_route(ax25_route *ax25_rt);
 
+extern rwlock_t ax25_route_lock;
+
+static inline void ax25_route_lock_use(void)
+{
+       read_lock(&ax25_route_lock);
+}
+
+static inline void ax25_route_lock_unuse(void)
+{
+       read_unlock(&ax25_route_lock);
+}
+
 static inline void ax25_put_route(ax25_route *ax25_rt)
 {
        if (refcount_dec_and_test(&ax25_rt->refcount))
index 00b5e78..74ff688 100644 (file)
@@ -39,6 +39,7 @@ struct inet_peer {
 
        u32                     metrics[RTAX_MAX];
        u32                     rate_tokens;    /* rate limiting for ICMP */
+       u32                     n_redirects;
        unsigned long           rate_last;
        /*
         * Once inet_peer is queued for deletion (refcnt == 0), following field
index c596976..9c8214d 100644 (file)
@@ -241,7 +241,7 @@ int fib_table_delete(struct net *, struct fib_table *, struct fib_config *,
                     struct netlink_ext_ack *extack);
 int fib_table_dump(struct fib_table *table, struct sk_buff *skb,
                   struct netlink_callback *cb, struct fib_dump_filter *filter);
-int fib_table_flush(struct net *net, struct fib_table *table);
+int fib_table_flush(struct net *net, struct fib_table *table, bool flush_all);
 struct fib_table *fib_trie_unmerge(struct fib_table *main_tb);
 void fib_table_flush_external(struct fib_table *table);
 void fib_free_table(struct fib_table *tb);
index 78fa0ac..5175fd6 100644 (file)
@@ -153,7 +153,8 @@ struct sk_buff *l3mdev_l3_rcv(struct sk_buff *skb, u16 proto)
 
        if (netif_is_l3_slave(skb->dev))
                master = netdev_master_upper_dev_get_rcu(skb->dev);
-       else if (netif_is_l3_master(skb->dev))
+       else if (netif_is_l3_master(skb->dev) ||
+                netif_has_l3_rx_handler(skb->dev))
                master = skb->dev;
 
        if (master && master->l3mdev_ops->l3mdev_l3_rcv)
index 7d5cda7..3e370cb 100644 (file)
@@ -84,7 +84,6 @@ struct flow_offload {
 struct nf_flow_route {
        struct {
                struct dst_entry        *dst;
-               int                     ifindex;
        } tuple[FLOW_OFFLOAD_DIR_MAX];
 };
 
index 841835a..b4984bb 100644 (file)
@@ -469,9 +469,7 @@ struct nft_set_binding {
 int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
                       struct nft_set_binding *binding);
 void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
-                         struct nft_set_binding *binding);
-void nf_tables_rebind_set(const struct nft_ctx *ctx, struct nft_set *set,
-                         struct nft_set_binding *binding);
+                         struct nft_set_binding *binding, bool commit);
 void nf_tables_destroy_set(const struct nft_ctx *ctx, struct nft_set *set);
 
 /**
@@ -721,6 +719,13 @@ struct nft_expr_type {
 #define NFT_EXPR_STATEFUL              0x1
 #define NFT_EXPR_GC                    0x2
 
+enum nft_trans_phase {
+       NFT_TRANS_PREPARE,
+       NFT_TRANS_ABORT,
+       NFT_TRANS_COMMIT,
+       NFT_TRANS_RELEASE
+};
+
 /**
  *     struct nft_expr_ops - nf_tables expression operations
  *
@@ -750,7 +755,8 @@ struct nft_expr_ops {
        void                            (*activate)(const struct nft_ctx *ctx,
                                                    const struct nft_expr *expr);
        void                            (*deactivate)(const struct nft_ctx *ctx,
-                                                     const struct nft_expr *expr);
+                                                     const struct nft_expr *expr,
+                                                     enum nft_trans_phase phase);
        void                            (*destroy)(const struct nft_ctx *ctx,
                                                   const struct nft_expr *expr);
        void                            (*destroy_clone)(const struct nft_ctx *ctx,
@@ -1323,12 +1329,15 @@ struct nft_trans_rule {
 struct nft_trans_set {
        struct nft_set                  *set;
        u32                             set_id;
+       bool                            bound;
 };
 
 #define nft_trans_set(trans)   \
        (((struct nft_trans_set *)trans->data)->set)
 #define nft_trans_set_id(trans)        \
        (((struct nft_trans_set *)trans->data)->set_id)
+#define nft_trans_set_bound(trans)     \
+       (((struct nft_trans_set *)trans->data)->bound)
 
 struct nft_trans_chain {
        bool                            update;
index b669fe6..98f31c7 100644 (file)
@@ -63,10 +63,11 @@ struct pnpipehdr {
                u8              state_after_reset;      /* reset request */
                u8              error_code;             /* any response */
                u8              pep_type;               /* status indication */
-               u8              data[1];
+               u8              data0;                  /* anything else */
        };
+       u8                      data[];
 };
-#define other_pep_type         data[1]
+#define other_pep_type         data[0]
 
 static inline struct pnpipehdr *pnp_hdr(struct sk_buff *skb)
 {
index 2b229f7..f43f935 100644 (file)
@@ -1277,7 +1277,7 @@ static inline void sk_sockets_allocated_inc(struct sock *sk)
        percpu_counter_inc(sk->sk_prot->sockets_allocated);
 }
 
-static inline int
+static inline u64
 sk_sockets_allocated_read_positive(struct sock *sk)
 {
        return percpu_counter_read_positive(sk->sk_prot->sockets_allocated);
index 2a6ac8d..1486b60 100644 (file)
@@ -120,6 +120,8 @@ struct tls_rec {
        struct scatterlist sg_aead_out[2];
 
        char aad_space[TLS_AAD_SPACE_SIZE];
+       u8 iv_data[TLS_CIPHER_AES_GCM_128_IV_SIZE +
+                  TLS_CIPHER_AES_GCM_128_SALT_SIZE];
        struct aead_request aead_req;
        u8 aead_req_ctx[];
 };
index 7298a53..85386be 100644 (file)
@@ -853,7 +853,7 @@ static inline void xfrm_pols_put(struct xfrm_policy **pols, int npols)
                xfrm_pol_put(pols[i]);
 }
 
-void __xfrm_state_destroy(struct xfrm_state *);
+void __xfrm_state_destroy(struct xfrm_state *, bool);
 
 static inline void __xfrm_state_put(struct xfrm_state *x)
 {
@@ -863,7 +863,13 @@ static inline void __xfrm_state_put(struct xfrm_state *x)
 static inline void xfrm_state_put(struct xfrm_state *x)
 {
        if (refcount_dec_and_test(&x->refcnt))
-               __xfrm_state_destroy(x);
+               __xfrm_state_destroy(x, false);
+}
+
+static inline void xfrm_state_put_sync(struct xfrm_state *x)
+{
+       if (refcount_dec_and_test(&x->refcnt))
+               __xfrm_state_destroy(x, true);
 }
 
 static inline void xfrm_state_hold(struct xfrm_state *x)
@@ -1590,7 +1596,7 @@ struct xfrmk_spdinfo {
 
 struct xfrm_state *xfrm_find_acq_byseq(struct net *net, u32 mark, u32 seq);
 int xfrm_state_delete(struct xfrm_state *x);
-int xfrm_state_flush(struct net *net, u8 proto, bool task_valid);
+int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync);
 int xfrm_dev_state_flush(struct net *net, struct net_device *dev, bool task_valid);
 void xfrm_sad_getinfo(struct net *net, struct xfrmk_sadinfo *si);
 void xfrm_spd_getinfo(struct net *net, struct xfrmk_spdinfo *si);
index a3ceed3..80debf5 100644 (file)
@@ -2579,9 +2579,10 @@ struct ib_device {
 
        const struct uapi_definition   *driver_def;
        enum rdma_driver_id             driver_id;
+
        /*
-        * Provides synchronization between device unregistration and netlink
-        * commands on a device. To be used only by core.
+        * Positive refcount indicates that the device is currently
+        * registered and cannot be unregistered.
         */
        refcount_t refcount;
        struct completion unreg_completion;
@@ -3926,6 +3927,25 @@ static inline bool ib_access_writable(int access_flags)
 int ib_check_mr_status(struct ib_mr *mr, u32 check_mask,
                       struct ib_mr_status *mr_status);
 
+/**
+ * ib_device_try_get: Hold a registration lock
+ * device: The device to lock
+ *
+ * A device under an active registration lock cannot become unregistered. It
+ * is only possible to obtain a registration lock on a device that is fully
+ * registered, otherwise this function returns false.
+ *
+ * The registration lock is only necessary for actions which require the
+ * device to still be registered. Uses that only require the device pointer to
+ * be valid should use get_device(&ibdev->dev) to hold the memory.
+ *
+ */
+static inline bool ib_device_try_get(struct ib_device *dev)
+{
+       return refcount_inc_not_zero(&dev->refcount);
+}
+
+void ib_device_put(struct ib_device *device);
 struct net_device *ib_get_net_dev_by_params(struct ib_device *dev, u8 port,
                                            u16 pkey, const union ib_gid *gid,
                                            const struct sockaddr *addr);
index 0cdc399..c5188ff 100644 (file)
@@ -173,7 +173,11 @@ static inline void snd_compr_drain_notify(struct snd_compr_stream *stream)
        if (snd_BUG_ON(!stream))
                return;
 
-       stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+       if (stream->direction == SND_COMPRESS_PLAYBACK)
+               stream->runtime->state = SNDRV_PCM_STATE_SETUP;
+       else
+               stream->runtime->state = SNDRV_PCM_STATE_PREPARED;
+
        wake_up(&stream->runtime->sleep);
 }
 
index 7fa48b1..cc7c8d4 100644 (file)
@@ -68,6 +68,7 @@ struct hda_bus {
        unsigned int response_reset:1;  /* controller was reset */
        unsigned int in_reset:1;        /* during reset operation */
        unsigned int no_response_fallback:1; /* don't fallback at RIRB error */
+       unsigned int bus_probing :1;    /* during probing process */
 
        int primary_dig_out_type;       /* primary digital out PCM type */
        unsigned int mixer_assigned;    /* codec addr for mixer name */
index 8ec1de8..e665f11 100644 (file)
@@ -985,6 +985,12 @@ struct snd_soc_dai_link {
        /* Do not create a PCM for this DAI link (Backend link) */
        unsigned int ignore:1;
 
+       /*
+        * This driver uses legacy platform naming. Set by the core, machine
+        * drivers should not modify this value.
+        */
+       unsigned int legacy_platform:1;
+
        struct list_head list; /* DAI link list of the soc card */
        struct snd_soc_dobj dobj; /* For topology */
 };
index 33d2918..e3f005e 100644 (file)
@@ -25,6 +25,7 @@
 enum afs_call_trace {
        afs_call_trace_alloc,
        afs_call_trace_free,
+       afs_call_trace_get,
        afs_call_trace_put,
        afs_call_trace_wake,
        afs_call_trace_work,
@@ -159,6 +160,7 @@ enum afs_file_error {
 #define afs_call_traces \
        EM(afs_call_trace_alloc,                "ALLOC") \
        EM(afs_call_trace_free,                 "FREE ") \
+       EM(afs_call_trace_get,                  "GET  ") \
        EM(afs_call_trace_put,                  "PUT  ") \
        EM(afs_call_trace_wake,                 "WAKE ") \
        E_(afs_call_trace_work,                 "WORK ")
diff --git a/include/uapi/asm-generic/shmparam.h b/include/uapi/asm-generic/shmparam.h
deleted file mode 100644 (file)
index 8b78c0b..0000000
+++ /dev/null
@@ -1,7 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-#ifndef __ASM_GENERIC_SHMPARAM_H
-#define __ASM_GENERIC_SHMPARAM_H
-
-#define SHMLBA PAGE_SIZE        /* attach addr a multiple of this */
-
-#endif /* _ASM_GENERIC_SHMPARAM_H */
diff --git a/include/uapi/linux/android/binder_ctl.h b/include/uapi/linux/android/binder_ctl.h
deleted file mode 100644 (file)
index 65b2efd..0000000
+++ /dev/null
@@ -1,35 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
-/*
- * Copyright (C) 2018 Canonical Ltd.
- *
- */
-
-#ifndef _UAPI_LINUX_BINDER_CTL_H
-#define _UAPI_LINUX_BINDER_CTL_H
-
-#include <linux/android/binder.h>
-#include <linux/types.h>
-#include <linux/ioctl.h>
-
-#define BINDERFS_MAX_NAME 255
-
-/**
- * struct binderfs_device - retrieve information about a new binder device
- * @name:   the name to use for the new binderfs binder device
- * @major:  major number allocated for binderfs binder devices
- * @minor:  minor number allocated for the new binderfs binder device
- *
- */
-struct binderfs_device {
-       char name[BINDERFS_MAX_NAME + 1];
-       __u8 major;
-       __u8 minor;
-};
-
-/**
- * Allocate a new binder device.
- */
-#define BINDER_CTL_ADD _IOWR('b', 1, struct binderfs_device)
-
-#endif /* _UAPI_LINUX_BINDER_CTL_H */
-
diff --git a/include/uapi/linux/android/binderfs.h b/include/uapi/linux/android/binderfs.h
new file mode 100644 (file)
index 0000000..8741047
--- /dev/null
@@ -0,0 +1,35 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+/*
+ * Copyright (C) 2018 Canonical Ltd.
+ *
+ */
+
+#ifndef _UAPI_LINUX_BINDERFS_H
+#define _UAPI_LINUX_BINDERFS_H
+
+#include <linux/android/binder.h>
+#include <linux/types.h>
+#include <linux/ioctl.h>
+
+#define BINDERFS_MAX_NAME 255
+
+/**
+ * struct binderfs_device - retrieve information about a new binder device
+ * @name:   the name to use for the new binderfs binder device
+ * @major:  major number allocated for binderfs binder devices
+ * @minor:  minor number allocated for the new binderfs binder device
+ *
+ */
+struct binderfs_device {
+       char name[BINDERFS_MAX_NAME + 1];
+       __u32 major;
+       __u32 minor;
+};
+
+/**
+ * Allocate a new binder device.
+ */
+#define BINDER_CTL_ADD _IOWR('b', 1, struct binderfs_device)
+
+#endif /* _UAPI_LINUX_BINDERFS_H */
+
index 36a7e3f..f28acd9 100644 (file)
@@ -400,6 +400,8 @@ enum {
 /* do not define AUDIT_ARCH_PPCLE since it is not supported by audit */
 #define AUDIT_ARCH_PPC64       (EM_PPC64|__AUDIT_ARCH_64BIT)
 #define AUDIT_ARCH_PPC64LE     (EM_PPC64|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_RISCV32     (EM_RISCV|__AUDIT_ARCH_LE)
+#define AUDIT_ARCH_RISCV64     (EM_RISCV|__AUDIT_ARCH_64BIT|__AUDIT_ARCH_LE)
 #define AUDIT_ARCH_S390                (EM_S390)
 #define AUDIT_ARCH_S390X       (EM_S390|__AUDIT_ARCH_64BIT)
 #define AUDIT_ARCH_SH          (EM_SH)
index 6fa38d0..498eec8 100644 (file)
@@ -138,6 +138,7 @@ struct blk_zone_range {
  * @BLKRESETZONE: Reset the write pointer of the zones in the specified
  *                sector range. The sector range must be zone aligned.
  * @BLKGETZONESZ: Get the device zone size in number of 512 B sectors.
+ * @BLKGETNRZONES: Get the total number of zones of the device.
  */
 #define BLKREPORTZONE  _IOWR(0x12, 130, struct blk_zone_report)
 #define BLKRESETZONE   _IOW(0x12, 131, struct blk_zone_range)
index f6052e7..a55cb8b 100644 (file)
@@ -268,7 +268,7 @@ struct sockaddr_in {
 #define        IN_MULTICAST(a)         IN_CLASSD(a)
 #define        IN_MULTICAST_NET        0xe0000000
 
-#define        IN_BADCLASS(a)          ((((long int) (a) ) == 0xffffffff)
+#define        IN_BADCLASS(a)          (((long int) (a) ) == (long int)0xffffffff)
 #define        IN_EXPERIMENTAL(a)      IN_BADCLASS((a))
 
 #define        IN_CLASSE(a)            ((((long int) (a)) & 0xf0000000) == 0xf0000000)
index 14565d7..e8baca8 100644 (file)
@@ -137,15 +137,21 @@ enum {
        INET_DIAG_TCLASS,
        INET_DIAG_SKMEMINFO,
        INET_DIAG_SHUTDOWN,
-       INET_DIAG_DCTCPINFO,
-       INET_DIAG_PROTOCOL,  /* response attribute only */
+
+       /*
+        * Next extenstions cannot be requested in struct inet_diag_req_v2:
+        * its field idiag_ext has only 8 bits.
+        */
+
+       INET_DIAG_DCTCPINFO,    /* request as INET_DIAG_VEGASINFO */
+       INET_DIAG_PROTOCOL,     /* response attribute only */
        INET_DIAG_SKV6ONLY,
        INET_DIAG_LOCALS,
        INET_DIAG_PEERS,
        INET_DIAG_PAD,
-       INET_DIAG_MARK,
-       INET_DIAG_BBRINFO,
-       INET_DIAG_CLASS_ID,
+       INET_DIAG_MARK,         /* only with CAP_NET_ADMIN */
+       INET_DIAG_BBRINFO,      /* request as INET_DIAG_VEGASINFO */
+       INET_DIAG_CLASS_ID,     /* request as INET_DIAG_TCLASS */
        INET_DIAG_MD5SIG,
        __INET_DIAG_MAX,
 };
index fb78f6f..f056b2a 100644 (file)
  */
 
 struct input_event {
-#if (__BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)) && !defined(__KERNEL)
+#if (__BITS_PER_LONG != 32 || !defined(__USE_TIME_BITS64)) && !defined(__KERNEL__)
        struct timeval time;
 #define input_event_sec time.tv_sec
 #define input_event_usec time.tv_usec
 #else
        __kernel_ulong_t __sec;
+#if defined(__sparc__) && defined(__arch64__)
+       unsigned int __usec;
+#else
        __kernel_ulong_t __usec;
+#endif
 #define input_event_sec  __sec
 #define input_event_usec __usec
 #endif
index d73d839..1bc794a 100644 (file)
@@ -147,7 +147,7 @@ struct ptp_pin_desc {
 #define PTP_SYS_OFFSET_PRECISE \
        _IOWR(PTP_CLK_MAGIC, 8, struct ptp_sys_offset_precise)
 #define PTP_SYS_OFFSET_EXTENDED \
-       _IOW(PTP_CLK_MAGIC, 9, struct ptp_sys_offset_extended)
+       _IOWR(PTP_CLK_MAGIC, 9, struct ptp_sys_offset_extended)
 
 struct ptp_extts_event {
        struct ptp_clock_time t; /* Time event occured. */
index 1196e1c..ff8e7dc 100644 (file)
 /* This feature indicates support for the packed virtqueue layout. */
 #define VIRTIO_F_RING_PACKED           34
 
+/*
+ * This feature indicates that memory accesses by the driver and the
+ * device are ordered in a way described by the platform.
+ */
+#define VIRTIO_F_ORDER_PLATFORM                36
+
 /*
  * Does the device support Single Root I/O Virtualization?
  */
index 2414f8a..4c4e24c 100644 (file)
@@ -213,14 +213,4 @@ struct vring_packed_desc {
        __le16 flags;
 };
 
-struct vring_packed {
-       unsigned int num;
-
-       struct vring_packed_desc *desc;
-
-       struct vring_packed_desc_event *driver;
-
-       struct vring_packed_desc_event *device;
-};
-
 #endif /* _UAPI_LINUX_VIRTIO_RING_H */
index ef3c7ec..eb76b38 100644 (file)
@@ -52,6 +52,11 @@ struct hns_roce_ib_create_srq {
        __aligned_u64 que_addr;
 };
 
+struct hns_roce_ib_create_srq_resp {
+       __u32   srqn;
+       __u32   reserved;
+};
+
 struct hns_roce_ib_create_qp {
        __aligned_u64 buf_addr;
        __aligned_u64 db_addr;
index d13fd49..6e73f02 100644 (file)
@@ -78,6 +78,7 @@ enum pvrdma_wr_opcode {
        PVRDMA_WR_MASKED_ATOMIC_FETCH_AND_ADD,
        PVRDMA_WR_BIND_MW,
        PVRDMA_WR_REG_SIG_MR,
+       PVRDMA_WR_ERROR,
 };
 
 enum pvrdma_wc_status {
index 59a2607..2ca9164 100644 (file)
@@ -1,17 +1,6 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-#ifndef _ASM_ARM_XEN_PAGE_COHERENT_H
-#define _ASM_ARM_XEN_PAGE_COHERENT_H
-
-#include <asm/page.h>
-#include <asm/dma-mapping.h>
-#include <linux/dma-mapping.h>
-
-static inline const struct dma_map_ops *xen_get_dma_ops(struct device *dev)
-{
-       if (dev && dev->archdata.dev_dma_ops)
-               return dev->archdata.dev_dma_ops;
-       return get_arch_dma_ops(NULL);
-}
+#ifndef _XEN_ARM_PAGE_COHERENT_H
+#define _XEN_ARM_PAGE_COHERENT_H
 
 void __xen_dma_map_page(struct device *hwdev, struct page *page,
             dma_addr_t dev_addr, unsigned long offset, size_t size,
@@ -21,87 +10,7 @@ void __xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
                unsigned long attrs);
 void __xen_dma_sync_single_for_cpu(struct device *hwdev,
                dma_addr_t handle, size_t size, enum dma_data_direction dir);
-
 void __xen_dma_sync_single_for_device(struct device *hwdev,
                dma_addr_t handle, size_t size, enum dma_data_direction dir);
 
-static inline void *xen_alloc_coherent_pages(struct device *hwdev, size_t size,
-               dma_addr_t *dma_handle, gfp_t flags, unsigned long attrs)
-{
-       return xen_get_dma_ops(hwdev)->alloc(hwdev, size, dma_handle, flags, attrs);
-}
-
-static inline void xen_free_coherent_pages(struct device *hwdev, size_t size,
-               void *cpu_addr, dma_addr_t dma_handle, unsigned long attrs)
-{
-       xen_get_dma_ops(hwdev)->free(hwdev, size, cpu_addr, dma_handle, attrs);
-}
-
-static inline void xen_dma_map_page(struct device *hwdev, struct page *page,
-            dma_addr_t dev_addr, unsigned long offset, size_t size,
-            enum dma_data_direction dir, unsigned long attrs)
-{
-       unsigned long page_pfn = page_to_xen_pfn(page);
-       unsigned long dev_pfn = XEN_PFN_DOWN(dev_addr);
-       unsigned long compound_pages =
-               (1<<compound_order(page)) * XEN_PFN_PER_PAGE;
-       bool local = (page_pfn <= dev_pfn) &&
-               (dev_pfn - page_pfn < compound_pages);
-
-       /*
-        * Dom0 is mapped 1:1, while the Linux page can span across
-        * multiple Xen pages, it's not possible for it to contain a
-        * mix of local and foreign Xen pages. So if the first xen_pfn
-        * == mfn the page is local otherwise it's a foreign page
-        * grant-mapped in dom0. If the page is local we can safely
-        * call the native dma_ops function, otherwise we call the xen
-        * specific function.
-        */
-       if (local)
-               xen_get_dma_ops(hwdev)->map_page(hwdev, page, offset, size, dir, attrs);
-       else
-               __xen_dma_map_page(hwdev, page, dev_addr, offset, size, dir, attrs);
-}
-
-static inline void xen_dma_unmap_page(struct device *hwdev, dma_addr_t handle,
-               size_t size, enum dma_data_direction dir, unsigned long attrs)
-{
-       unsigned long pfn = PFN_DOWN(handle);
-       /*
-        * Dom0 is mapped 1:1, while the Linux page can be spanned accross
-        * multiple Xen page, it's not possible to have a mix of local and
-        * foreign Xen page. Dom0 is mapped 1:1, so calling pfn_valid on a
-        * foreign mfn will always return false. If the page is local we can
-        * safely call the native dma_ops function, otherwise we call the xen
-        * specific function.
-        */
-       if (pfn_valid(pfn)) {
-               if (xen_get_dma_ops(hwdev)->unmap_page)
-                       xen_get_dma_ops(hwdev)->unmap_page(hwdev, handle, size, dir, attrs);
-       } else
-               __xen_dma_unmap_page(hwdev, handle, size, dir, attrs);
-}
-
-static inline void xen_dma_sync_single_for_cpu(struct device *hwdev,
-               dma_addr_t handle, size_t size, enum dma_data_direction dir)
-{
-       unsigned long pfn = PFN_DOWN(handle);
-       if (pfn_valid(pfn)) {
-               if (xen_get_dma_ops(hwdev)->sync_single_for_cpu)
-                       xen_get_dma_ops(hwdev)->sync_single_for_cpu(hwdev, handle, size, dir);
-       } else
-               __xen_dma_sync_single_for_cpu(hwdev, handle, size, dir);
-}
-
-static inline void xen_dma_sync_single_for_device(struct device *hwdev,
-               dma_addr_t handle, size_t size, enum dma_data_direction dir)
-{
-       unsigned long pfn = PFN_DOWN(handle);
-       if (pfn_valid(pfn)) {
-               if (xen_get_dma_ops(hwdev)->sync_single_for_device)
-                       xen_get_dma_ops(hwdev)->sync_single_for_device(hwdev, handle, size, dir);
-       } else
-               __xen_dma_sync_single_for_device(hwdev, handle, size, dir);
-}
-
-#endif /* _ASM_ARM_XEN_PAGE_COHERENT_H */
+#endif /* _XEN_ARM_PAGE_COHERENT_H */
index d47cb77..c9386a3 100644 (file)
@@ -512,6 +512,17 @@ config PSI_DEFAULT_DISABLED
          per default but can be enabled through passing psi=1 on the
          kernel commandline during boot.
 
+         This feature adds some code to the task wakeup and sleep
+         paths of the scheduler. The overhead is too low to affect
+         common scheduling-intense workloads in practice (such as
+         webservers, memcache), but it does show up in artificial
+         scheduler stress tests, such as hackbench.
+
+         If you are paranoid and not sure what the kernel will be
+         used for, say Y.
+
+         Say N if unsure.
+
 endmenu # "CPU/Task time and stats accounting"
 
 config CPU_ISOLATION
@@ -825,7 +836,7 @@ config CGROUP_PIDS
          PIDs controller is designed to stop this from happening.
 
          It should be noted that organisational operations (such as attaching
-         to a cgroup hierarchy will *not* be blocked by the PIDs controller),
+         to a cgroup hierarchy) will *not* be blocked by the PIDs controller,
          since the PIDs limit only affects a process's ability to fork, not to
          attach to a cgroup.
 
@@ -1124,6 +1135,7 @@ config LD_DEAD_CODE_DATA_ELIMINATION
        bool "Dead code and data elimination (EXPERIMENTAL)"
        depends on HAVE_LD_DEAD_CODE_DATA_ELIMINATION
        depends on EXPERT
+       depends on !(FUNCTION_TRACER && CC_IS_GCC && GCC_VERSION < 40800)
        depends on $(cc-option,-ffunction-sections -fdata-sections)
        depends on $(ld-option,--gc-sections)
        help
index 7cea802..fca8996 100644 (file)
@@ -550,6 +550,7 @@ skip:
        initrd_end = 0;
 }
 
+#ifdef CONFIG_BLK_DEV_RAM
 #define BUF_SIZE 1024
 static void __init clean_rootfs(void)
 {
@@ -596,6 +597,7 @@ static void __init clean_rootfs(void)
        ksys_close(fd);
        kfree(buf);
 }
+#endif
 
 static int __init populate_rootfs(void)
 {
@@ -638,10 +640,8 @@ static int __init populate_rootfs(void)
                printk(KERN_INFO "Unpacking initramfs...\n");
                err = unpack_to_rootfs((char *)initrd_start,
                        initrd_end - initrd_start);
-               if (err) {
+               if (err)
                        printk(KERN_EMERG "Initramfs unpacking failed: %s\n", err);
-                       clean_rootfs();
-               }
                free_initrd();
 #endif
        }
index e2e80ca..c86a1c8 100644 (file)
@@ -695,7 +695,6 @@ asmlinkage __visible void __init start_kernel(void)
                initrd_start = 0;
        }
 #endif
-       page_ext_init();
        kmemleak_init();
        setup_per_cpu_pageset();
        numa_policy_init();
@@ -1131,6 +1130,8 @@ static noinline void __init kernel_init_freeable(void)
        sched_init_smp();
 
        page_alloc_init_late();
+       /* Initialize page ext after all struct pages are initialized. */
+       page_ext_init();
 
        do_basic_setup();
 
index 715f9fc..c57bd10 100644 (file)
@@ -467,7 +467,7 @@ static const struct btf_kind_operations *btf_type_ops(const struct btf_type *t)
        return kind_ops[BTF_INFO_KIND(t->info)];
 }
 
-bool btf_name_offset_valid(const struct btf *btf, u32 offset)
+static bool btf_name_offset_valid(const struct btf *btf, u32 offset)
 {
        return BTF_STR_OFFSET_VALID(offset) &&
                offset < btf->hdr.str_len;
@@ -1219,8 +1219,6 @@ static void btf_bitfield_seq_show(void *data, u8 bits_offset,
        u8 nr_copy_bits;
        u64 print_num;
 
-       data += BITS_ROUNDDOWN_BYTES(bits_offset);
-       bits_offset = BITS_PER_BYTE_MASKED(bits_offset);
        nr_copy_bits = nr_bits + bits_offset;
        nr_copy_bytes = BITS_ROUNDUP_BYTES(nr_copy_bits);
 
@@ -1255,7 +1253,9 @@ static void btf_int_bits_seq_show(const struct btf *btf,
         * BTF_INT_OFFSET() cannot exceed 64 bits.
         */
        total_bits_offset = bits_offset + BTF_INT_OFFSET(int_data);
-       btf_bitfield_seq_show(data, total_bits_offset, nr_bits, m);
+       data += BITS_ROUNDDOWN_BYTES(total_bits_offset);
+       bits_offset = BITS_PER_BYTE_MASKED(total_bits_offset);
+       btf_bitfield_seq_show(data, bits_offset, nr_bits, m);
 }
 
 static void btf_int_seq_show(const struct btf *btf, const struct btf_type *t,
@@ -1459,7 +1459,8 @@ static int btf_modifier_resolve(struct btf_verifier_env *env,
 
                /* "typedef void new_void", "const void"...etc */
                if (!btf_type_is_void(next_type) &&
-                   !btf_type_is_fwd(next_type)) {
+                   !btf_type_is_fwd(next_type) &&
+                   !btf_type_is_func_proto(next_type)) {
                        btf_verifier_log_type(env, v->t, "Invalid type_id");
                        return -EINVAL;
                }
@@ -2001,12 +2002,12 @@ static void btf_struct_seq_show(const struct btf *btf, const struct btf_type *t,
 
                member_offset = btf_member_bit_offset(t, member);
                bitfield_size = btf_member_bitfield_size(t, member);
+               bytes_offset = BITS_ROUNDDOWN_BYTES(member_offset);
+               bits8_offset = BITS_PER_BYTE_MASKED(member_offset);
                if (bitfield_size) {
-                       btf_bitfield_seq_show(data, member_offset,
+                       btf_bitfield_seq_show(data + bytes_offset, bits8_offset,
                                              bitfield_size, m);
                } else {
-                       bytes_offset = BITS_ROUNDDOWN_BYTES(member_offset);
-                       bits8_offset = BITS_PER_BYTE_MASKED(member_offset);
                        ops = btf_type_ops(member_type);
                        ops->seq_show(btf, member_type, member->type,
                                      data + bytes_offset, bits8_offset, m);
index 9425c2f..d17d055 100644 (file)
@@ -572,7 +572,7 @@ int __cgroup_bpf_run_filter_skb(struct sock *sk,
        bpf_compute_and_save_data_end(skb, &saved_data_end);
 
        ret = BPF_PROG_RUN_ARRAY(cgrp->bpf.effective[type], skb,
-                                bpf_prog_run_save_cb);
+                                __bpf_prog_run_save_cb);
        bpf_restore_data_end(skb, saved_data_end);
        __skb_pull(skb, offset);
        skb->sk = save_sk;
@@ -718,6 +718,7 @@ cgroup_dev_func_proto(enum bpf_func_id func_id, const struct bpf_prog *prog)
        case BPF_FUNC_trace_printk:
                if (capable(CAP_SYS_ADMIN))
                        return bpf_get_trace_printk_proto();
+               /* fall through */
        default:
                return NULL;
        }
index 4b7c767..f927411 100644 (file)
@@ -686,7 +686,7 @@ static void free_htab_elem(struct bpf_htab *htab, struct htab_elem *l)
        }
 
        if (htab_is_prealloc(htab)) {
-               pcpu_freelist_push(&htab->freelist, &l->fnode);
+               __pcpu_freelist_push(&htab->freelist, &l->fnode);
        } else {
                atomic_dec(&htab->count);
                l->htab = htab;
@@ -748,7 +748,7 @@ static struct htab_elem *alloc_htab_elem(struct bpf_htab *htab, void *key,
                } else {
                        struct pcpu_freelist_node *l;
 
-                       l = pcpu_freelist_pop(&htab->freelist);
+                       l = __pcpu_freelist_pop(&htab->freelist);
                        if (!l)
                                return ERR_PTR(-E2BIG);
                        l_new = container_of(l, struct htab_elem, fnode);
index abf1002..93a5cbb 100644 (file)
@@ -471,6 +471,7 @@ static int trie_delete_elem(struct bpf_map *map, void *_key)
        }
 
        if (!node || node->prefixlen != key->prefixlen ||
+           node->prefixlen != matchlen ||
            (node->flags & LPM_TREE_NODE_FLAG_IM)) {
                ret = -ENOENT;
                goto out;
index 99d243e..52378d3 100644 (file)
@@ -12,6 +12,7 @@
 struct bpf_map *bpf_map_meta_alloc(int inner_map_ufd)
 {
        struct bpf_map *inner_map, *inner_map_meta;
+       u32 inner_map_meta_size;
        struct fd f;
 
        f = fdget(inner_map_ufd);
@@ -36,7 +37,12 @@ struct bpf_map *bpf_map_meta_alloc(int inner_map_ufd)
                return ERR_PTR(-EINVAL);
        }
 
-       inner_map_meta = kzalloc(sizeof(*inner_map_meta), GFP_USER);
+       inner_map_meta_size = sizeof(*inner_map_meta);
+       /* In some cases verifier needs to access beyond just base map. */
+       if (inner_map->ops == &array_map_ops)
+               inner_map_meta_size = sizeof(struct bpf_array);
+
+       inner_map_meta = kzalloc(inner_map_meta_size, GFP_USER);
        if (!inner_map_meta) {
                fdput(f);
                return ERR_PTR(-ENOMEM);
@@ -46,9 +52,16 @@ struct bpf_map *bpf_map_meta_alloc(int inner_map_ufd)
        inner_map_meta->key_size = inner_map->key_size;
        inner_map_meta->value_size = inner_map->value_size;
        inner_map_meta->map_flags = inner_map->map_flags;
-       inner_map_meta->ops = inner_map->ops;
        inner_map_meta->max_entries = inner_map->max_entries;
 
+       /* Misc members not needed in bpf_map_meta_equal() check. */
+       inner_map_meta->ops = inner_map->ops;
+       if (inner_map->ops == &array_map_ops) {
+               inner_map_meta->unpriv_array = inner_map->unpriv_array;
+               container_of(inner_map_meta, struct bpf_array, map)->index_mask =
+                    container_of(inner_map, struct bpf_array, map)->index_mask;
+       }
+
        fdput(f);
        return inner_map_meta;
 }
index 673fa6f..0c1b4ba 100644 (file)
@@ -28,8 +28,8 @@ void pcpu_freelist_destroy(struct pcpu_freelist *s)
        free_percpu(s->freelist);
 }
 
-static inline void __pcpu_freelist_push(struct pcpu_freelist_head *head,
-                                       struct pcpu_freelist_node *node)
+static inline void ___pcpu_freelist_push(struct pcpu_freelist_head *head,
+                                        struct pcpu_freelist_node *node)
 {
        raw_spin_lock(&head->lock);
        node->next = head->first;
@@ -37,12 +37,22 @@ static inline void __pcpu_freelist_push(struct pcpu_freelist_head *head,
        raw_spin_unlock(&head->lock);
 }
 
-void pcpu_freelist_push(struct pcpu_freelist *s,
+void __pcpu_freelist_push(struct pcpu_freelist *s,
                        struct pcpu_freelist_node *node)
 {
        struct pcpu_freelist_head *head = this_cpu_ptr(s->freelist);
 
-       __pcpu_freelist_push(head, node);
+       ___pcpu_freelist_push(head, node);
+}
+
+void pcpu_freelist_push(struct pcpu_freelist *s,
+                       struct pcpu_freelist_node *node)
+{
+       unsigned long flags;
+
+       local_irq_save(flags);
+       __pcpu_freelist_push(s, node);
+       local_irq_restore(flags);
 }
 
 void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
@@ -63,7 +73,7 @@ void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
        for_each_possible_cpu(cpu) {
 again:
                head = per_cpu_ptr(s->freelist, cpu);
-               __pcpu_freelist_push(head, buf);
+               ___pcpu_freelist_push(head, buf);
                i++;
                buf += elem_size;
                if (i == nr_elems)
@@ -74,14 +84,12 @@ again:
        local_irq_restore(flags);
 }
 
-struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *s)
+struct pcpu_freelist_node *__pcpu_freelist_pop(struct pcpu_freelist *s)
 {
        struct pcpu_freelist_head *head;
        struct pcpu_freelist_node *node;
-       unsigned long flags;
        int orig_cpu, cpu;
 
-       local_irq_save(flags);
        orig_cpu = cpu = raw_smp_processor_id();
        while (1) {
                head = per_cpu_ptr(s->freelist, cpu);
@@ -89,16 +97,25 @@ struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *s)
                node = head->first;
                if (node) {
                        head->first = node->next;
-                       raw_spin_unlock_irqrestore(&head->lock, flags);
+                       raw_spin_unlock(&head->lock);
                        return node;
                }
                raw_spin_unlock(&head->lock);
                cpu = cpumask_next(cpu, cpu_possible_mask);
                if (cpu >= nr_cpu_ids)
                        cpu = 0;
-               if (cpu == orig_cpu) {
-                       local_irq_restore(flags);
+               if (cpu == orig_cpu)
                        return NULL;
-               }
        }
 }
+
+struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *s)
+{
+       struct pcpu_freelist_node *ret;
+       unsigned long flags;
+
+       local_irq_save(flags);
+       ret = __pcpu_freelist_pop(s);
+       local_irq_restore(flags);
+       return ret;
+}
index 3049aae..c396011 100644 (file)
@@ -22,8 +22,12 @@ struct pcpu_freelist_node {
        struct pcpu_freelist_node *next;
 };
 
+/* pcpu_freelist_* do spin_lock_irqsave. */
 void pcpu_freelist_push(struct pcpu_freelist *, struct pcpu_freelist_node *);
 struct pcpu_freelist_node *pcpu_freelist_pop(struct pcpu_freelist *);
+/* __pcpu_freelist_* do spin_lock only. caller must disable irqs. */
+void __pcpu_freelist_push(struct pcpu_freelist *, struct pcpu_freelist_node *);
+struct pcpu_freelist_node *__pcpu_freelist_pop(struct pcpu_freelist *);
 void pcpu_freelist_populate(struct pcpu_freelist *s, void *buf, u32 elem_size,
                            u32 nr_elems);
 int pcpu_freelist_init(struct pcpu_freelist *);
index 90daf28..950ab2f 100644 (file)
@@ -44,7 +44,7 @@ static void do_up_read(struct irq_work *entry)
        struct stack_map_irq_work *work;
 
        work = container_of(entry, struct stack_map_irq_work, irq_work);
-       up_read(work->sem);
+       up_read_non_owner(work->sem);
        work->sem = NULL;
 }
 
@@ -180,11 +180,14 @@ static inline int stack_map_parse_build_id(void *page_addr,
 
                if (nhdr->n_type == BPF_BUILD_ID &&
                    nhdr->n_namesz == sizeof("GNU") &&
-                   nhdr->n_descsz == BPF_BUILD_ID_SIZE) {
+                   nhdr->n_descsz > 0 &&
+                   nhdr->n_descsz <= BPF_BUILD_ID_SIZE) {
                        memcpy(build_id,
                               note_start + note_offs +
                               ALIGN(sizeof("GNU"), 4) + sizeof(Elf32_Nhdr),
-                              BPF_BUILD_ID_SIZE);
+                              nhdr->n_descsz);
+                       memset(build_id + nhdr->n_descsz, 0,
+                              BPF_BUILD_ID_SIZE - nhdr->n_descsz);
                        return 0;
                }
                new_offs = note_offs + sizeof(Elf32_Nhdr) +
@@ -260,7 +263,7 @@ static int stack_map_get_build_id(struct vm_area_struct *vma,
                return -EFAULT; /* page not mapped */
 
        ret = -EINVAL;
-       page_addr = page_address(page);
+       page_addr = kmap_atomic(page);
        ehdr = (Elf32_Ehdr *)page_addr;
 
        /* compare magic x7f "ELF" */
@@ -276,6 +279,7 @@ static int stack_map_get_build_id(struct vm_area_struct *vma,
        else if (ehdr->e_ident[EI_CLASS] == ELFCLASS64)
                ret = stack_map_get_build_id_64(page_addr, build_id);
 out:
+       kunmap_atomic(page_addr);
        put_page(page);
        return ret;
 }
@@ -310,6 +314,7 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
                for (i = 0; i < trace_nr; i++) {
                        id_offs[i].status = BPF_STACK_BUILD_ID_IP;
                        id_offs[i].ip = ips[i];
+                       memset(id_offs[i].build_id, 0, BPF_BUILD_ID_SIZE);
                }
                return;
        }
@@ -320,6 +325,7 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
                        /* per entry fall back to ips */
                        id_offs[i].status = BPF_STACK_BUILD_ID_IP;
                        id_offs[i].ip = ips[i];
+                       memset(id_offs[i].build_id, 0, BPF_BUILD_ID_SIZE);
                        continue;
                }
                id_offs[i].offset = (vma->vm_pgoff << PAGE_SHIFT) + ips[i]
@@ -332,6 +338,12 @@ static void stack_map_get_build_id_offset(struct bpf_stack_build_id *id_offs,
        } else {
                work->sem = &current->mm->mmap_sem;
                irq_work_queue(&work->irq_work);
+               /*
+                * The irq_work will release the mmap_sem with
+                * up_read_non_owner(). The rwsem_release() is called
+                * here to release the lock from lockdep's perspective.
+                */
+               rwsem_release(&current->mm->mmap_sem.dep_map, 1, _RET_IP_);
        }
 }
 
index b155cd1..8577bb7 100644 (file)
@@ -713,8 +713,13 @@ static int map_lookup_elem(union bpf_attr *attr)
 
        if (bpf_map_is_dev_bound(map)) {
                err = bpf_map_offload_lookup_elem(map, key, value);
-       } else if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
-                  map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
+               goto done;
+       }
+
+       preempt_disable();
+       this_cpu_inc(bpf_prog_active);
+       if (map->map_type == BPF_MAP_TYPE_PERCPU_HASH ||
+           map->map_type == BPF_MAP_TYPE_LRU_PERCPU_HASH) {
                err = bpf_percpu_hash_copy(map, key, value);
        } else if (map->map_type == BPF_MAP_TYPE_PERCPU_ARRAY) {
                err = bpf_percpu_array_copy(map, key, value);
@@ -744,7 +749,10 @@ static int map_lookup_elem(union bpf_attr *attr)
                }
                rcu_read_unlock();
        }
+       this_cpu_dec(bpf_prog_active);
+       preempt_enable();
 
+done:
        if (err)
                goto free_value;
 
index f6bc62a..8f295b7 100644 (file)
@@ -1617,12 +1617,13 @@ static int check_flow_keys_access(struct bpf_verifier_env *env, int off,
        return 0;
 }
 
-static int check_sock_access(struct bpf_verifier_env *env, u32 regno, int off,
-                            int size, enum bpf_access_type t)
+static int check_sock_access(struct bpf_verifier_env *env, int insn_idx,
+                            u32 regno, int off, int size,
+                            enum bpf_access_type t)
 {
        struct bpf_reg_state *regs = cur_regs(env);
        struct bpf_reg_state *reg = &regs[regno];
-       struct bpf_insn_access_aux info;
+       struct bpf_insn_access_aux info = {};
 
        if (reg->smin_value < 0) {
                verbose(env, "R%d min value is negative, either use unsigned index or do a if (index >=0) check.\n",
@@ -1636,6 +1637,8 @@ static int check_sock_access(struct bpf_verifier_env *env, u32 regno, int off,
                return -EACCES;
        }
 
+       env->insn_aux_data[insn_idx].ctx_field_size = info.ctx_field_size;
+
        return 0;
 }
 
@@ -2032,7 +2035,7 @@ static int check_mem_access(struct bpf_verifier_env *env, int insn_idx, u32 regn
                        verbose(env, "cannot write into socket\n");
                        return -EACCES;
                }
-               err = check_sock_access(env, regno, off, size, t);
+               err = check_sock_access(env, insn_idx, regno, off, size, t);
                if (!err && value_regno >= 0)
                        mark_reg_unknown(env, regs, value_regno);
        } else {
@@ -3103,6 +3106,40 @@ static int retrieve_ptr_limit(const struct bpf_reg_state *ptr_reg,
        }
 }
 
+static bool can_skip_alu_sanitation(const struct bpf_verifier_env *env,
+                                   const struct bpf_insn *insn)
+{
+       return env->allow_ptr_leaks || BPF_SRC(insn->code) == BPF_K;
+}
+
+static int update_alu_sanitation_state(struct bpf_insn_aux_data *aux,
+                                      u32 alu_state, u32 alu_limit)
+{
+       /* If we arrived here from different branches with different
+        * state or limits to sanitize, then this won't work.
+        */
+       if (aux->alu_state &&
+           (aux->alu_state != alu_state ||
+            aux->alu_limit != alu_limit))
+               return -EACCES;
+
+       /* Corresponding fixup done in fixup_bpf_calls(). */
+       aux->alu_state = alu_state;
+       aux->alu_limit = alu_limit;
+       return 0;
+}
+
+static int sanitize_val_alu(struct bpf_verifier_env *env,
+                           struct bpf_insn *insn)
+{
+       struct bpf_insn_aux_data *aux = cur_aux(env);
+
+       if (can_skip_alu_sanitation(env, insn))
+               return 0;
+
+       return update_alu_sanitation_state(aux, BPF_ALU_NON_POINTER, 0);
+}
+
 static int sanitize_ptr_alu(struct bpf_verifier_env *env,
                            struct bpf_insn *insn,
                            const struct bpf_reg_state *ptr_reg,
@@ -3117,7 +3154,7 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
        struct bpf_reg_state tmp;
        bool ret;
 
-       if (env->allow_ptr_leaks || BPF_SRC(insn->code) == BPF_K)
+       if (can_skip_alu_sanitation(env, insn))
                return 0;
 
        /* We already marked aux for masking from non-speculative
@@ -3133,19 +3170,8 @@ static int sanitize_ptr_alu(struct bpf_verifier_env *env,
 
        if (retrieve_ptr_limit(ptr_reg, &alu_limit, opcode, off_is_neg))
                return 0;
-
-       /* If we arrived here from different branches with different
-        * limits to sanitize, then this won't work.
-        */
-       if (aux->alu_state &&
-           (aux->alu_state != alu_state ||
-            aux->alu_limit != alu_limit))
+       if (update_alu_sanitation_state(aux, alu_state, alu_limit))
                return -EACCES;
-
-       /* Corresponding fixup done in fixup_bpf_calls(). */
-       aux->alu_state = alu_state;
-       aux->alu_limit = alu_limit;
-
 do_sim:
        /* Simulate and find potential out-of-bounds access under
         * speculative execution from truncation as a result of
@@ -3418,6 +3444,8 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
        s64 smin_val, smax_val;
        u64 umin_val, umax_val;
        u64 insn_bitness = (BPF_CLASS(insn->code) == BPF_ALU64) ? 64 : 32;
+       u32 dst = insn->dst_reg;
+       int ret;
 
        if (insn_bitness == 32) {
                /* Relevant for 32-bit RSH: Information can propagate towards
@@ -3452,6 +3480,11 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
 
        switch (opcode) {
        case BPF_ADD:
+               ret = sanitize_val_alu(env, insn);
+               if (ret < 0) {
+                       verbose(env, "R%d tried to add from different pointers or scalars\n", dst);
+                       return ret;
+               }
                if (signed_add_overflows(dst_reg->smin_value, smin_val) ||
                    signed_add_overflows(dst_reg->smax_value, smax_val)) {
                        dst_reg->smin_value = S64_MIN;
@@ -3471,6 +3504,11 @@ static int adjust_scalar_min_max_vals(struct bpf_verifier_env *env,
                dst_reg->var_off = tnum_add(dst_reg->var_off, src_reg.var_off);
                break;
        case BPF_SUB:
+               ret = sanitize_val_alu(env, insn);
+               if (ret < 0) {
+                       verbose(env, "R%d tried to sub from different pointers or scalars\n", dst);
+                       return ret;
+               }
                if (signed_sub_overflows(dst_reg->smin_value, smax_val) ||
                    signed_sub_overflows(dst_reg->smax_value, smin_val)) {
                        /* Overflow possible, we know nothing */
index 91d5c38..d1c6d15 100644 (file)
@@ -376,9 +376,6 @@ void __weak arch_smt_update(void) { }
 
 #ifdef CONFIG_HOTPLUG_SMT
 enum cpuhp_smt_control cpu_smt_control __read_mostly = CPU_SMT_ENABLED;
-EXPORT_SYMBOL_GPL(cpu_smt_control);
-
-static bool cpu_smt_available __read_mostly;
 
 void __init cpu_smt_disable(bool force)
 {
@@ -397,25 +394,11 @@ void __init cpu_smt_disable(bool force)
 
 /*
  * The decision whether SMT is supported can only be done after the full
- * CPU identification. Called from architecture code before non boot CPUs
- * are brought up.
- */
-void __init cpu_smt_check_topology_early(void)
-{
-       if (!topology_smt_supported())
-               cpu_smt_control = CPU_SMT_NOT_SUPPORTED;
-}
-
-/*
- * If SMT was disabled by BIOS, detect it here, after the CPUs have been
- * brought online. This ensures the smt/l1tf sysfs entries are consistent
- * with reality. cpu_smt_available is set to true during the bringup of non
- * boot CPUs when a SMT sibling is detected. Note, this may overwrite
- * cpu_smt_control's previous setting.
+ * CPU identification. Called from architecture code.
  */
 void __init cpu_smt_check_topology(void)
 {
-       if (!cpu_smt_available)
+       if (!topology_smt_supported())
                cpu_smt_control = CPU_SMT_NOT_SUPPORTED;
 }
 
@@ -428,18 +411,10 @@ early_param("nosmt", smt_cmdline_disable);
 
 static inline bool cpu_smt_allowed(unsigned int cpu)
 {
-       if (topology_is_primary_thread(cpu))
+       if (cpu_smt_control == CPU_SMT_ENABLED)
                return true;
 
-       /*
-        * If the CPU is not a 'primary' thread and the booted_once bit is
-        * set then the processor has SMT support. Store this information
-        * for the late check of SMT support in cpu_smt_check_topology().
-        */
-       if (per_cpu(cpuhp_state, cpu).booted_once)
-               cpu_smt_available = true;
-
-       if (cpu_smt_control == CPU_SMT_ENABLED)
+       if (topology_is_primary_thread(cpu))
                return true;
 
        /*
@@ -2090,10 +2065,8 @@ static int cpuhp_smt_disable(enum cpuhp_smt_control ctrlval)
                 */
                cpuhp_offline_cpu_device(cpu);
        }
-       if (!ret) {
+       if (!ret)
                cpu_smt_control = ctrlval;
-               arch_smt_update();
-       }
        cpu_maps_update_done();
        return ret;
 }
@@ -2104,7 +2077,6 @@ static int cpuhp_smt_enable(void)
 
        cpu_maps_update_begin();
        cpu_smt_control = CPU_SMT_ENABLED;
-       arch_smt_update();
        for_each_present_cpu(cpu) {
                /* Skip online CPUs and CPUs on offline nodes */
                if (cpu_online(cpu) || !node_online(cpu_to_node(cpu)))
index d636177..1fb6fd6 100644 (file)
@@ -378,6 +378,8 @@ void __init swiotlb_exit(void)
                memblock_free_late(io_tlb_start,
                                   PAGE_ALIGN(io_tlb_nslabs << IO_TLB_SHIFT));
        }
+       io_tlb_start = 0;
+       io_tlb_end = 0;
        io_tlb_nslabs = 0;
        max_segment = 0;
 }
index 3cd13a3..26d6eda 100644 (file)
@@ -436,18 +436,18 @@ int perf_proc_update_handler(struct ctl_table *table, int write,
                void __user *buffer, size_t *lenp,
                loff_t *ppos)
 {
-       int ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
-
-       if (ret || !write)
-               return ret;
-
+       int ret;
+       int perf_cpu = sysctl_perf_cpu_time_max_percent;
        /*
         * If throttling is disabled don't allow the write:
         */
-       if (sysctl_perf_cpu_time_max_percent == 100 ||
-           sysctl_perf_cpu_time_max_percent == 0)
+       if (write && (perf_cpu == 100 || perf_cpu == 0))
                return -EINVAL;
 
+       ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos);
+       if (ret || !write)
+               return ret;
+
        max_samples_per_tick = DIV_ROUND_UP(sysctl_perf_event_sample_rate, HZ);
        perf_sample_period_ns = NSEC_PER_SEC / sysctl_perf_event_sample_rate;
        update_perf_cpu_limits();
@@ -4963,6 +4963,11 @@ static void __perf_event_period(struct perf_event *event,
        }
 }
 
+static int perf_event_check_period(struct perf_event *event, u64 value)
+{
+       return event->pmu->check_period(event, value);
+}
+
 static int perf_event_period(struct perf_event *event, u64 __user *arg)
 {
        u64 value;
@@ -4979,6 +4984,9 @@ static int perf_event_period(struct perf_event *event, u64 __user *arg)
        if (event->attr.freq && value > sysctl_perf_event_sample_rate)
                return -EINVAL;
 
+       if (perf_event_check_period(event, value))
+               return -EINVAL;
+
        event_function_call(event, __perf_event_period, &value);
 
        return 0;
@@ -9391,6 +9399,11 @@ static int perf_pmu_nop_int(struct pmu *pmu)
        return 0;
 }
 
+static int perf_event_nop_int(struct perf_event *event, u64 value)
+{
+       return 0;
+}
+
 static DEFINE_PER_CPU(unsigned int, nop_txn_flags);
 
 static void perf_pmu_start_txn(struct pmu *pmu, unsigned int flags)
@@ -9691,6 +9704,9 @@ got_cpu_context:
                pmu->pmu_disable = perf_pmu_nop_void;
        }
 
+       if (!pmu->check_period)
+               pmu->check_period = perf_event_nop_int;
+
        if (!pmu->event_idx)
                pmu->event_idx = perf_event_idx_default;
 
index 4a99370..5ab4fe3 100644 (file)
@@ -734,6 +734,9 @@ struct ring_buffer *rb_alloc(int nr_pages, long watermark, int cpu, int flags)
        size = sizeof(struct ring_buffer);
        size += nr_pages * sizeof(void *);
 
+       if (order_base_2(size) >= PAGE_SHIFT+MAX_ORDER)
+               goto fail;
+
        rb = kzalloc(size, GFP_KERNEL);
        if (!rb)
                goto fail;
index 2d14979..2639a30 100644 (file)
@@ -307,7 +307,7 @@ void rcuwait_wake_up(struct rcuwait *w)
         *        MB (A)              MB (B)
         *    [L] cond            [L] tsk
         */
-       smp_rmb(); /* (B) */
+       smp_mb(); /* (B) */
 
        /*
         * Avoid using task_rcu_dereference() magic as long as we are careful,
@@ -558,12 +558,14 @@ static struct task_struct *find_alive_thread(struct task_struct *p)
        return NULL;
 }
 
-static struct task_struct *find_child_reaper(struct task_struct *father)
+static struct task_struct *find_child_reaper(struct task_struct *father,
+                                               struct list_head *dead)
        __releases(&tasklist_lock)
        __acquires(&tasklist_lock)
 {
        struct pid_namespace *pid_ns = task_active_pid_ns(father);
        struct task_struct *reaper = pid_ns->child_reaper;
+       struct task_struct *p, *n;
 
        if (likely(reaper != father))
                return reaper;
@@ -579,6 +581,12 @@ static struct task_struct *find_child_reaper(struct task_struct *father)
                panic("Attempted to kill init! exitcode=0x%08x\n",
                        father->signal->group_exit_code ?: father->exit_code);
        }
+
+       list_for_each_entry_safe(p, n, dead, ptrace_entry) {
+               list_del_init(&p->ptrace_entry);
+               release_task(p);
+       }
+
        zap_pid_ns_processes(pid_ns);
        write_lock_irq(&tasklist_lock);
 
@@ -668,7 +676,7 @@ static void forget_original_parent(struct task_struct *father,
                exit_ptrace(father, dead);
 
        /* Can drop and reacquire tasklist_lock */
-       reaper = find_child_reaper(father);
+       reaper = find_child_reaper(father, dead);
        if (list_empty(&father->children))
                return;
 
@@ -866,6 +874,7 @@ void __noreturn do_exit(long code)
        exit_task_namespaces(tsk);
        exit_task_work(tsk);
        exit_thread(tsk);
+       exit_umh(tsk);
 
        /*
         * Flush inherited counters to the parent - before the parent
index a604599..b69248e 100644 (file)
@@ -217,6 +217,7 @@ static unsigned long *alloc_thread_stack_node(struct task_struct *tsk, int node)
                memset(s->addr, 0, THREAD_SIZE);
 
                tsk->stack_vm_area = s;
+               tsk->stack = s->addr;
                return s->addr;
        }
 
@@ -1833,8 +1834,6 @@ static __latent_entropy struct task_struct *copy_process(
 
        posix_cpu_timers_init(p);
 
-       p->start_time = ktime_get_ns();
-       p->real_start_time = ktime_get_boot_ns();
        p->io_context = NULL;
        audit_set_context(p, NULL);
        cgroup_fork(p);
@@ -2000,6 +1999,17 @@ static __latent_entropy struct task_struct *copy_process(
        if (retval)
                goto bad_fork_free_pid;
 
+       /*
+        * From this point on we must avoid any synchronous user-space
+        * communication until we take the tasklist-lock. In particular, we do
+        * not want user-space to be able to predict the process start-time by
+        * stalling fork(2) after we recorded the start_time but before it is
+        * visible to the system.
+        */
+
+       p->start_time = ktime_get_ns();
+       p->real_start_time = ktime_get_boot_ns();
+
        /*
         * Make it visible to the rest of the system, but dont wake it up yet.
         * Need tasklist lock for parent etc handling!
index be3bff2..a0514e0 100644 (file)
@@ -1452,11 +1452,7 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
        if (WARN(q->pi_state || q->rt_waiter, "refusing to wake PI futex\n"))
                return;
 
-       /*
-        * Queue the task for later wakeup for after we've released
-        * the hb->lock. wake_q_add() grabs reference to p.
-        */
-       wake_q_add(wake_q, p);
+       get_task_struct(p);
        __unqueue_futex(q);
        /*
         * The waiting task can free the futex_q as soon as q->lock_ptr = NULL
@@ -1466,6 +1462,13 @@ static void mark_wake_futex(struct wake_q_head *wake_q, struct futex_q *q)
         * plist_del in __unqueue_futex().
         */
        smp_store_release(&q->lock_ptr, NULL);
+
+       /*
+        * Queue the task for later wakeup for after we've released
+        * the hb->lock. wake_q_add() grabs reference to p.
+        */
+       wake_q_add(wake_q, p);
+       put_task_struct(p);
 }
 
 /*
@@ -2218,11 +2221,11 @@ static inline struct futex_hash_bucket *queue_lock(struct futex_q *q)
         * decrement the counter at queue_unlock() when some error has
         * occurred and we don't end up adding the task to the list.
         */
-       hb_waiters_inc(hb);
+       hb_waiters_inc(hb); /* implies smp_mb(); (A) */
 
        q->lock_ptr = &hb->lock;
 
-       spin_lock(&hb->lock); /* implies smp_mb(); (A) */
+       spin_lock(&hb->lock);
        return hb;
 }
 
@@ -2858,35 +2861,39 @@ retry_private:
         * and BUG when futex_unlock_pi() interleaves with this.
         *
         * Therefore acquire wait_lock while holding hb->lock, but drop the
-        * latter before calling rt_mutex_start_proxy_lock(). This still fully
-        * serializes against futex_unlock_pi() as that does the exact same
-        * lock handoff sequence.
+        * latter before calling __rt_mutex_start_proxy_lock(). This
+        * interleaves with futex_unlock_pi() -- which does a similar lock
+        * handoff -- such that the latter can observe the futex_q::pi_state
+        * before __rt_mutex_start_proxy_lock() is done.
         */
        raw_spin_lock_irq(&q.pi_state->pi_mutex.wait_lock);
        spin_unlock(q.lock_ptr);
+       /*
+        * __rt_mutex_start_proxy_lock() unconditionally enqueues the @rt_waiter
+        * such that futex_unlock_pi() is guaranteed to observe the waiter when
+        * it sees the futex_q::pi_state.
+        */
        ret = __rt_mutex_start_proxy_lock(&q.pi_state->pi_mutex, &rt_waiter, current);
        raw_spin_unlock_irq(&q.pi_state->pi_mutex.wait_lock);
 
        if (ret) {
                if (ret == 1)
                        ret = 0;
-
-               spin_lock(q.lock_ptr);
-               goto no_block;
+               goto cleanup;
        }
 
-
        if (unlikely(to))
                hrtimer_start_expires(&to->timer, HRTIMER_MODE_ABS);
 
        ret = rt_mutex_wait_proxy_lock(&q.pi_state->pi_mutex, to, &rt_waiter);
 
+cleanup:
        spin_lock(q.lock_ptr);
        /*
-        * If we failed to acquire the lock (signal/timeout), we must
+        * If we failed to acquire the lock (deadlock/signal/timeout), we must
         * first acquire the hb->lock before removing the lock from the
-        * rt_mutex waitqueue, such that we can keep the hb and rt_mutex
-        * wait lists consistent.
+        * rt_mutex waitqueue, such that we can keep the hb and rt_mutex wait
+        * lists consistent.
         *
         * In particular; it is important that futex_unlock_pi() can not
         * observe this inconsistency.
@@ -3010,6 +3017,10 @@ retry:
                 * there is no point where we hold neither; and therefore
                 * wake_futex_pi() must observe a state consistent with what we
                 * observed.
+                *
+                * In particular; this forces __rt_mutex_start_proxy() to
+                * complete such that we're guaranteed to observe the
+                * rt_waiter. Also see the WARN in wake_futex_pi().
                 */
                raw_spin_lock_irq(&pi_state->pi_mutex.wait_lock);
                spin_unlock(&hb->lock);
index ee062b7..ef8ad36 100644 (file)
@@ -457,7 +457,7 @@ static int alloc_descs(unsigned int start, unsigned int cnt, int node,
 
        /* Validate affinity mask(s) */
        if (affinity) {
-               for (i = 0; i < cnt; i++, i++) {
+               for (i = 0; i < cnt; i++) {
                        if (cpumask_empty(&affinity[i].mask))
                                return -EINVAL;
                }
index a4888ce..84b54a1 100644 (file)
@@ -393,6 +393,9 @@ int irq_setup_affinity(struct irq_desc *desc)
        }
 
        cpumask_and(&mask, cpu_online_mask, set);
+       if (cpumask_empty(&mask))
+               cpumask_copy(&mask, cpu_online_mask);
+
        if (node != NUMA_NO_NODE) {
                const struct cpumask *nodemask = cpumask_of_node(node);
 
index 581edcc..978d63a 100644 (file)
@@ -1726,12 +1726,33 @@ void rt_mutex_proxy_unlock(struct rt_mutex *lock,
        rt_mutex_set_owner(lock, NULL);
 }
 
+/**
+ * __rt_mutex_start_proxy_lock() - Start lock acquisition for another task
+ * @lock:              the rt_mutex to take
+ * @waiter:            the pre-initialized rt_mutex_waiter
+ * @task:              the task to prepare
+ *
+ * Starts the rt_mutex acquire; it enqueues the @waiter and does deadlock
+ * detection. It does not wait, see rt_mutex_wait_proxy_lock() for that.
+ *
+ * NOTE: does _NOT_ remove the @waiter on failure; must either call
+ * rt_mutex_wait_proxy_lock() or rt_mutex_cleanup_proxy_lock() after this.
+ *
+ * Returns:
+ *  0 - task blocked on lock
+ *  1 - acquired the lock for task, caller should wake it up
+ * <0 - error
+ *
+ * Special API call for PI-futex support.
+ */
 int __rt_mutex_start_proxy_lock(struct rt_mutex *lock,
                              struct rt_mutex_waiter *waiter,
                              struct task_struct *task)
 {
        int ret;
 
+       lockdep_assert_held(&lock->wait_lock);
+
        if (try_to_take_rt_mutex(lock, task, NULL))
                return 1;
 
@@ -1749,9 +1770,6 @@ int __rt_mutex_start_proxy_lock(struct rt_mutex *lock,
                ret = 0;
        }
 
-       if (unlikely(ret))
-               remove_waiter(lock, waiter);
-
        debug_rt_mutex_print_deadlock(waiter);
 
        return ret;
@@ -1763,12 +1781,18 @@ int __rt_mutex_start_proxy_lock(struct rt_mutex *lock,
  * @waiter:            the pre-initialized rt_mutex_waiter
  * @task:              the task to prepare
  *
+ * Starts the rt_mutex acquire; it enqueues the @waiter and does deadlock
+ * detection. It does not wait, see rt_mutex_wait_proxy_lock() for that.
+ *
+ * NOTE: unlike __rt_mutex_start_proxy_lock this _DOES_ remove the @waiter
+ * on failure.
+ *
  * Returns:
  *  0 - task blocked on lock
  *  1 - acquired the lock for task, caller should wake it up
  * <0 - error
  *
- * Special API call for FUTEX_REQUEUE_PI support.
+ * Special API call for PI-futex support.
  */
 int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
                              struct rt_mutex_waiter *waiter,
@@ -1778,6 +1802,8 @@ int rt_mutex_start_proxy_lock(struct rt_mutex *lock,
 
        raw_spin_lock_irq(&lock->wait_lock);
        ret = __rt_mutex_start_proxy_lock(lock, waiter, task);
+       if (unlikely(ret))
+               remove_waiter(lock, waiter);
        raw_spin_unlock_irq(&lock->wait_lock);
 
        return ret;
@@ -1845,7 +1871,8 @@ int rt_mutex_wait_proxy_lock(struct rt_mutex *lock,
  * @lock:              the rt_mutex we were woken on
  * @waiter:            the pre-initialized rt_mutex_waiter
  *
- * Attempt to clean up after a failed rt_mutex_wait_proxy_lock().
+ * Attempt to clean up after a failed __rt_mutex_start_proxy_lock() or
+ * rt_mutex_wait_proxy_lock().
  *
  * Unless we acquired the lock; we're still enqueued on the wait-list and can
  * in fact still be granted ownership until we're removed. Therefore we can
index 09b1800..50d9af6 100644 (file)
@@ -198,15 +198,22 @@ static void __rwsem_mark_wake(struct rw_semaphore *sem,
                woken++;
                tsk = waiter->task;
 
-               wake_q_add(wake_q, tsk);
+               get_task_struct(tsk);
                list_del(&waiter->list);
                /*
-                * Ensure that the last operation is setting the reader
+                * Ensure calling get_task_struct() before setting the reader
                 * waiter to nil such that rwsem_down_read_failed() cannot
                 * race with do_exit() by always holding a reference count
                 * to the task to wakeup.
                 */
                smp_store_release(&waiter->task, NULL);
+               /*
+                * Ensure issuing the wakeup (either by us or someone else)
+                * after setting the reader waiter to nil.
+                */
+               wake_q_add(wake_q, tsk);
+               /* wake_q_add() already take the task ref */
+               put_task_struct(tsk);
        }
 
        adjustment = woken * RWSEM_ACTIVE_READ_BIAS - adjustment;
index 04f2486..9e0f523 100644 (file)
@@ -428,6 +428,8 @@ static struct dentry *relay_create_buf_file(struct rchan *chan,
        dentry = chan->cb->create_buf_file(tmpname, chan->parent,
                                           S_IRUSR, buf,
                                           &chan->is_global);
+       if (IS_ERR(dentry))
+               dentry = NULL;
 
        kfree(tmpname);
 
@@ -461,7 +463,7 @@ static struct rchan_buf *relay_open_buf(struct rchan *chan, unsigned int cpu)
                dentry = chan->cb->create_buf_file(NULL, NULL,
                                                   S_IRUSR, buf,
                                                   &chan->is_global);
-               if (WARN_ON(dentry))
+               if (IS_ERR_OR_NULL(dentry))
                        goto free_buf;
        }
 
index a674c7d..d8d76a6 100644 (file)
@@ -396,6 +396,18 @@ static bool set_nr_if_polling(struct task_struct *p)
 #endif
 #endif
 
+/**
+ * wake_q_add() - queue a wakeup for 'later' waking.
+ * @head: the wake_q_head to add @task to
+ * @task: the task to queue for 'later' wakeup
+ *
+ * Queue a task for later wakeup, most likely by the wake_up_q() call in the
+ * same context, _HOWEVER_ this is not guaranteed, the wakeup can come
+ * instantly.
+ *
+ * This function must be used as-if it were wake_up_process(); IOW the task
+ * must be ready to be woken at this location.
+ */
 void wake_q_add(struct wake_q_head *head, struct task_struct *task)
 {
        struct wake_q_node *node = &task->wake_q;
@@ -405,10 +417,11 @@ void wake_q_add(struct wake_q_head *head, struct task_struct *task)
         * its already queued (either by us or someone else) and will get the
         * wakeup due to that.
         *
-        * This cmpxchg() executes a full barrier, which pairs with the full
-        * barrier executed by the wakeup in wake_up_q().
+        * In order to ensure that a pending wakeup will observe our pending
+        * state, even in the failed case, an explicit smp_mb() must be used.
         */
-       if (cmpxchg(&node->next, NULL, WAKE_Q_TAIL))
+       smp_mb__before_atomic();
+       if (cmpxchg_relaxed(&node->next, NULL, WAKE_Q_TAIL))
                return;
 
        get_task_struct(task);
index 50aa2ab..310d063 100644 (file)
@@ -5980,6 +5980,7 @@ static inline int find_idlest_cpu(struct sched_domain *sd, struct task_struct *p
 
 #ifdef CONFIG_SCHED_SMT
 DEFINE_STATIC_KEY_FALSE(sched_smt_present);
+EXPORT_SYMBOL_GPL(sched_smt_present);
 
 static inline void set_idle_cores(int cpu, int val)
 {
index fe24de3..0e97ca9 100644 (file)
  * sampling of the aggregate task states would be.
  */
 
+#include "../workqueue_internal.h"
 #include <linux/sched/loadavg.h>
 #include <linux/seq_file.h>
 #include <linux/proc_fs.h>
@@ -321,7 +322,7 @@ static bool update_stats(struct psi_group *group)
        expires = group->next_update;
        if (now < expires)
                goto out;
-       if (now - expires > psi_period)
+       if (now - expires >= psi_period)
                missed_periods = div_u64(now - expires, psi_period);
 
        /*
@@ -480,9 +481,6 @@ static void psi_group_change(struct psi_group *group, int cpu,
                        groupc->tasks[t]++;
 
        write_seqcount_end(&groupc->seq);
-
-       if (!delayed_work_pending(&group->clock_work))
-               schedule_delayed_work(&group->clock_work, PSI_FREQ);
 }
 
 static struct psi_group *iterate_groups(struct task_struct *task, void **iter)
@@ -513,6 +511,7 @@ void psi_task_change(struct task_struct *task, int clear, int set)
 {
        int cpu = task_cpu(task);
        struct psi_group *group;
+       bool wake_clock = true;
        void *iter = NULL;
 
        if (!task->pid)
@@ -530,8 +529,22 @@ void psi_task_change(struct task_struct *task, int clear, int set)
        task->psi_flags &= ~clear;
        task->psi_flags |= set;
 
-       while ((group = iterate_groups(task, &iter)))
+       /*
+        * Periodic aggregation shuts off if there is a period of no
+        * task changes, so we wake it back up if necessary. However,
+        * don't do this if the task change is the aggregation worker
+        * itself going to sleep, or we'll ping-pong forever.
+        */
+       if (unlikely((clear & TSK_RUNNING) &&
+                    (task->flags & PF_WQ_WORKER) &&
+                    wq_worker_last_func(task) == psi_update_work))
+               wake_clock = false;
+
+       while ((group = iterate_groups(task, &iter))) {
                psi_group_change(group, cpu, clear, set);
+               if (wake_clock && !delayed_work_pending(&group->clock_work))
+                       schedule_delayed_work(&group->clock_work, PSI_FREQ);
+       }
 }
 
 void psi_memstall_tick(struct task_struct *task, int cpu)
index d7f5388..e815781 100644 (file)
@@ -976,6 +976,9 @@ static int seccomp_notify_release(struct inode *inode, struct file *file)
        struct seccomp_filter *filter = file->private_data;
        struct seccomp_knotif *knotif;
 
+       if (!filter)
+               return 0;
+
        mutex_lock(&filter->notify_lock);
 
        /*
@@ -1300,6 +1303,7 @@ out:
 out_put_fd:
        if (flags & SECCOMP_FILTER_FLAG_NEW_LISTENER) {
                if (ret < 0) {
+                       listener_f->private_data = NULL;
                        fput(listener_f);
                        put_unused_fd(listener);
                } else {
index e1d7ad8..57b7771 100644 (file)
@@ -688,6 +688,48 @@ int dequeue_signal(struct task_struct *tsk, sigset_t *mask, kernel_siginfo_t *in
 }
 EXPORT_SYMBOL_GPL(dequeue_signal);
 
+static int dequeue_synchronous_signal(kernel_siginfo_t *info)
+{
+       struct task_struct *tsk = current;
+       struct sigpending *pending = &tsk->pending;
+       struct sigqueue *q, *sync = NULL;
+
+       /*
+        * Might a synchronous signal be in the queue?
+        */
+       if (!((pending->signal.sig[0] & ~tsk->blocked.sig[0]) & SYNCHRONOUS_MASK))
+               return 0;
+
+       /*
+        * Return the first synchronous signal in the queue.
+        */
+       list_for_each_entry(q, &pending->list, list) {
+               /* Synchronous signals have a postive si_code */
+               if ((q->info.si_code > SI_USER) &&
+                   (sigmask(q->info.si_signo) & SYNCHRONOUS_MASK)) {
+                       sync = q;
+                       goto next;
+               }
+       }
+       return 0;
+next:
+       /*
+        * Check if there is another siginfo for the same signal.
+        */
+       list_for_each_entry_continue(q, &pending->list, list) {
+               if (q->info.si_signo == sync->info.si_signo)
+                       goto still_pending;
+       }
+
+       sigdelset(&pending->signal, sync->info.si_signo);
+       recalc_sigpending();
+still_pending:
+       list_del_init(&sync->list);
+       copy_siginfo(info, &sync->info);
+       __sigqueue_free(sync);
+       return info->si_signo;
+}
+
 /*
  * Tell a process that it has a new active signal..
  *
@@ -1057,10 +1099,9 @@ static int __send_signal(int sig, struct kernel_siginfo *info, struct task_struc
 
        result = TRACE_SIGNAL_DELIVERED;
        /*
-        * Skip useless siginfo allocation for SIGKILL SIGSTOP,
-        * and kernel threads.
+        * Skip useless siginfo allocation for SIGKILL and kernel threads.
         */
-       if (sig_kernel_only(sig) || (t->flags & PF_KTHREAD))
+       if ((sig == SIGKILL) || (t->flags & PF_KTHREAD))
                goto out_set;
 
        /*
@@ -2394,6 +2435,14 @@ relock:
                goto relock;
        }
 
+       /* Has this task already been marked for death? */
+       if (signal_group_exit(signal)) {
+               ksig->info.si_signo = signr = SIGKILL;
+               sigdelset(&current->pending.signal, SIGKILL);
+               recalc_sigpending();
+               goto fatal;
+       }
+
        for (;;) {
                struct k_sigaction *ka;
 
@@ -2407,7 +2456,15 @@ relock:
                        goto relock;
                }
 
-               signr = dequeue_signal(current, &current->blocked, &ksig->info);
+               /*
+                * Signals generated by the execution of an instruction
+                * need to be delivered before any other pending signals
+                * so that the instruction pointer in the signal stack
+                * frame points to the faulting instruction.
+                */
+               signr = dequeue_synchronous_signal(&ksig->info);
+               if (!signr)
+                       signr = dequeue_signal(current, &current->blocked, &ksig->info);
 
                if (!signr)
                        break; /* will return 0 */
@@ -2489,6 +2546,7 @@ relock:
                        continue;
                }
 
+       fatal:
                spin_unlock_irq(&sighand->siglock);
 
                /*
index 163c451..f4cf1b0 100644 (file)
@@ -584,8 +584,6 @@ void __init smp_init(void)
                num_nodes, (num_nodes > 1 ? "s" : ""),
                num_cpus,  (num_cpus  > 1 ? "s" : ""));
 
-       /* Final decision about SMT support */
-       cpu_smt_check_topology();
        /* Any cleanup work */
        smp_cpus_done(setup_max_cpus);
 }
index a48cbf1..f7eb62e 100644 (file)
@@ -1207,7 +1207,8 @@ DECLARE_RWSEM(uts_sem);
 /*
  * Work around broken programs that cannot handle "Linux 3.0".
  * Instead we map 3.x to 2.6.40+x, so e.g. 3.0 would be 2.6.40
- * And we map 4.x to 2.6.60+x, so 4.0 would be 2.6.60.
+ * And we map 4.x and later versions to 2.6.60+x, so 4.0/5.0/6.0/... would be
+ * 2.6.60.
  */
 static int override_release(char __user *release, size_t len)
 {
index 8f0644a..80f9552 100644 (file)
@@ -685,6 +685,7 @@ static int posix_cpu_timer_set(struct k_itimer *timer, int timer_flags,
         * set up the signal and overrun bookkeeping.
         */
        timer->it.cpu.incr = timespec64_to_ns(&new->it_interval);
+       timer->it_interval = ns_to_ktime(timer->it.cpu.incr);
 
        /*
         * This acts as a modification timestamp for the timer,
index 8b068ad..f1a86a0 100644 (file)
@@ -1204,22 +1204,12 @@ static int __bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *
 
 int bpf_probe_register(struct bpf_raw_event_map *btp, struct bpf_prog *prog)
 {
-       int err;
-
-       mutex_lock(&bpf_event_mutex);
-       err = __bpf_probe_register(btp, prog);
-       mutex_unlock(&bpf_event_mutex);
-       return err;
+       return __bpf_probe_register(btp, prog);
 }
 
 int bpf_probe_unregister(struct bpf_raw_event_map *btp, struct bpf_prog *prog)
 {
-       int err;
-
-       mutex_lock(&bpf_event_mutex);
-       err = tracepoint_probe_unregister(btp->tp, (void *)btp->bpf_func, prog);
-       mutex_unlock(&bpf_event_mutex);
-       return err;
+       return tracepoint_probe_unregister(btp->tp, (void *)btp->bpf_func, prog);
 }
 
 int bpf_get_perf_event_info(const struct perf_event *event, u32 *prog_id,
index c521b73..c4238b4 100644 (file)
@@ -3384,6 +3384,8 @@ static void print_func_help_header_irq(struct trace_buffer *buf, struct seq_file
        const char tgid_space[] = "          ";
        const char space[] = "  ";
 
+       print_event_info(buf, m);
+
        seq_printf(m, "#                          %s  _-----=> irqs-off\n",
                   tgid ? tgid_space : space);
        seq_printf(m, "#                          %s / _----=> need-resched\n",
index 5c19b8c..9eaf07f 100644 (file)
@@ -607,11 +607,17 @@ static int trace_kprobe_create(int argc, const char *argv[])
        char buf[MAX_EVENT_NAME_LEN];
        unsigned int flags = TPARG_FL_KERNEL;
 
-       /* argc must be >= 1 */
-       if (argv[0][0] == 'r') {
+       switch (argv[0][0]) {
+       case 'r':
                is_return = true;
                flags |= TPARG_FL_RETURN;
-       } else if (argv[0][0] != 'p' || argc < 2)
+               break;
+       case 'p':
+               break;
+       default:
+               return -ECANCELED;
+       }
+       if (argc < 2)
                return -ECANCELED;
 
        event = strchr(&argv[0][1], ':');
@@ -855,22 +861,14 @@ static const struct file_operations kprobe_profile_ops = {
 static nokprobe_inline int
 fetch_store_strlen(unsigned long addr)
 {
-       mm_segment_t old_fs;
        int ret, len = 0;
        u8 c;
 
-       old_fs = get_fs();
-       set_fs(KERNEL_DS);
-       pagefault_disable();
-
        do {
-               ret = __copy_from_user_inatomic(&c, (u8 *)addr + len, 1);
+               ret = probe_mem_read(&c, (u8 *)addr + len, 1);
                len++;
        } while (c && ret == 0 && len < MAX_STRING_SIZE);
 
-       pagefault_enable();
-       set_fs(old_fs);
-
        return (ret < 0) ? ret : len;
 }
 
index 5c56afc..4737bb8 100644 (file)
@@ -180,10 +180,12 @@ store_trace_args(void *data, struct trace_probe *tp, struct pt_regs *regs,
                if (unlikely(arg->dynamic))
                        *dl = make_data_loc(maxlen, dyndata - base);
                ret = process_fetch_insn(arg->code, regs, dl, base);
-               if (unlikely(ret < 0 && arg->dynamic))
+               if (unlikely(ret < 0 && arg->dynamic)) {
                        *dl = make_data_loc(0, dyndata - base);
-               else
+               } else {
                        dyndata += ret;
+                       maxlen -= ret;
+               }
        }
 }
 
index e335576..9bde07c 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright (C) IBM Corporation, 2010-2012
  * Author:     Srikar Dronamraju <srikar@linux.vnet.ibm.com>
  */
-#define pr_fmt(fmt)    "trace_kprobe: " fmt
+#define pr_fmt(fmt)    "trace_uprobe: " fmt
 
 #include <linux/ctype.h>
 #include <linux/module.h>
@@ -160,6 +160,13 @@ fetch_store_string(unsigned long addr, void *dest, void *base)
        if (ret >= 0) {
                if (ret == maxlen)
                        dst[ret - 1] = '\0';
+               else
+                       /*
+                        * Include the terminating null byte. In this case it
+                        * was copied by strncpy_from_user but not accounted
+                        * for in ret.
+                        */
+                       ret++;
                *(u32 *)dest = make_data_loc(ret, (void *)dst - base);
        }
 
index 0baa672..d937cba 100644 (file)
@@ -37,6 +37,8 @@ static kernel_cap_t usermodehelper_bset = CAP_FULL_SET;
 static kernel_cap_t usermodehelper_inheritable = CAP_FULL_SET;
 static DEFINE_SPINLOCK(umh_sysctl_lock);
 static DECLARE_RWSEM(umhelper_sem);
+static LIST_HEAD(umh_list);
+static DEFINE_MUTEX(umh_list_lock);
 
 static void call_usermodehelper_freeinfo(struct subprocess_info *info)
 {
@@ -100,10 +102,12 @@ static int call_usermodehelper_exec_async(void *data)
        commit_creds(new);
 
        sub_info->pid = task_pid_nr(current);
-       if (sub_info->file)
+       if (sub_info->file) {
                retval = do_execve_file(sub_info->file,
                                        sub_info->argv, sub_info->envp);
-       else
+               if (!retval)
+                       current->flags |= PF_UMH;
+       } else
                retval = do_execve(getname_kernel(sub_info->path),
                                   (const char __user *const __user *)sub_info->argv,
                                   (const char __user *const __user *)sub_info->envp);
@@ -517,6 +521,11 @@ int fork_usermode_blob(void *data, size_t len, struct umh_info *info)
                goto out;
 
        err = call_usermodehelper_exec(sub_info, UMH_WAIT_EXEC);
+       if (!err) {
+               mutex_lock(&umh_list_lock);
+               list_add(&info->list, &umh_list);
+               mutex_unlock(&umh_list_lock);
+       }
 out:
        fput(file);
        return err;
@@ -679,6 +688,26 @@ static int proc_cap_handler(struct ctl_table *table, int write,
        return 0;
 }
 
+void __exit_umh(struct task_struct *tsk)
+{
+       struct umh_info *info;
+       pid_t pid = tsk->pid;
+
+       mutex_lock(&umh_list_lock);
+       list_for_each_entry(info, &umh_list, list) {
+               if (info->pid == pid) {
+                       list_del(&info->list);
+                       mutex_unlock(&umh_list_lock);
+                       goto out;
+               }
+       }
+       mutex_unlock(&umh_list_lock);
+       return;
+out:
+       if (info->cleanup)
+               info->cleanup(info);
+}
+
 struct ctl_table usermodehelper_table[] = {
        {
                .procname       = "bset",
index 392be4b..fc5d23d 100644 (file)
@@ -909,6 +909,26 @@ struct task_struct *wq_worker_sleeping(struct task_struct *task)
        return to_wakeup ? to_wakeup->task : NULL;
 }
 
+/**
+ * wq_worker_last_func - retrieve worker's last work function
+ *
+ * Determine the last function a worker executed. This is called from
+ * the scheduler to get a worker's last known identity.
+ *
+ * CONTEXT:
+ * spin_lock_irq(rq->lock)
+ *
+ * Return:
+ * The last work function %current executed as a worker, NULL if it
+ * hasn't executed any work yet.
+ */
+work_func_t wq_worker_last_func(struct task_struct *task)
+{
+       struct worker *worker = kthread_data(task);
+
+       return worker->last_func;
+}
+
 /**
  * worker_set_flags - set worker flags and adjust nr_running accordingly
  * @worker: self
@@ -2184,6 +2204,9 @@ __acquires(&pool->lock)
        if (unlikely(cpu_intensive))
                worker_clr_flags(worker, WORKER_CPU_INTENSIVE);
 
+       /* tag the worker for identification in schedule() */
+       worker->last_func = worker->current_func;
+
        /* we're done with it, release */
        hash_del(&worker->hentry);
        worker->current_work = NULL;
index 66fbb5a..cb68b03 100644 (file)
@@ -53,6 +53,9 @@ struct worker {
 
        /* used only by rescuers to point to the target workqueue */
        struct workqueue_struct *rescue_wq;     /* I: the workqueue to rescue */
+
+       /* used by the scheduler to determine a worker's last known identity */
+       work_func_t             last_func;
 };
 
 /**
@@ -67,9 +70,10 @@ static inline struct worker *current_wq_worker(void)
 
 /*
  * Scheduler hooks for concurrency managed workqueue.  Only to be used from
- * sched/core.c and workqueue.c.
+ * sched/ and workqueue.c.
  */
 void wq_worker_waking_up(struct task_struct *task, int cpu);
 struct task_struct *wq_worker_sleeping(struct task_struct *task);
+work_func_t wq_worker_last_func(struct task_struct *task);
 
 #endif /* _KERNEL_WORKQUEUE_INTERNAL_H */
index c6659cb..59875eb 100644 (file)
@@ -768,9 +768,11 @@ all_leaves_cluster_together:
                new_s0->index_key[i] =
                        ops->get_key_chunk(index_key, i * ASSOC_ARRAY_KEY_CHUNK_SIZE);
 
-       blank = ULONG_MAX << (level & ASSOC_ARRAY_KEY_CHUNK_MASK);
-       pr_devel("blank off [%zu] %d: %lx\n", keylen - 1, level, blank);
-       new_s0->index_key[keylen - 1] &= ~blank;
+       if (level & ASSOC_ARRAY_KEY_CHUNK_MASK) {
+               blank = ULONG_MAX << (level & ASSOC_ARRAY_KEY_CHUNK_MASK);
+               pr_devel("blank off [%zu] %d: %lx\n", keylen - 1, level, blank);
+               new_s0->index_key[keylen - 1] &= ~blank;
+       }
 
        /* This now reduces to a node splitting exercise for which we'll need
         * to regenerate the disparity table.
index 45b1d67..4a20455 100644 (file)
@@ -206,8 +206,8 @@ u32 __pure __weak __crc32c_le(u32 crc, unsigned char const *p, size_t len)
 EXPORT_SYMBOL(crc32_le);
 EXPORT_SYMBOL(__crc32c_le);
 
-u32 crc32_le_base(u32, unsigned char const *, size_t) __alias(crc32_le);
-u32 __crc32c_le_base(u32, unsigned char const *, size_t) __alias(__crc32c_le);
+u32 __pure crc32_le_base(u32, unsigned char const *, size_t) __alias(crc32_le);
+u32 __pure __crc32c_le_base(u32, unsigned char const *, size_t) __alias(__crc32c_le);
 
 /*
  * This multiplies the polynomials x and y modulo the given modulus.
index 14436f4..30e0f97 100644 (file)
@@ -52,7 +52,7 @@ u32 int_sqrt64(u64 x)
        if (x <= ULONG_MAX)
                return int_sqrt((unsigned long) x);
 
-       m = 1ULL << (fls64(x) & ~1ULL);
+       m = 1ULL << ((fls64(x) - 1) & ~1ULL);
        while (m != 0) {
                b = y + m;
                y >>= 1;
index 65c2d06..5b382c1 100644 (file)
 static inline bool sbitmap_deferred_clear(struct sbitmap *sb, int index)
 {
        unsigned long mask, val;
-       unsigned long __maybe_unused flags;
        bool ret = false;
+       unsigned long flags;
 
-       /* Silence bogus lockdep warning */
-#if defined(CONFIG_LOCKDEP)
-       local_irq_save(flags);
-#endif
-       spin_lock(&sb->map[index].swap_lock);
+       spin_lock_irqsave(&sb->map[index].swap_lock, flags);
 
        if (!sb->map[index].cleared)
                goto out_unlock;
@@ -54,10 +50,7 @@ static inline bool sbitmap_deferred_clear(struct sbitmap *sb, int index)
 
        ret = true;
 out_unlock:
-       spin_unlock(&sb->map[index].swap_lock);
-#if defined(CONFIG_LOCKDEP)
-       local_irq_restore(flags);
-#endif
+       spin_unlock_irqrestore(&sb->map[index].swap_lock, flags);
        return ret;
 }
 
index d82d022..9cf7762 100644 (file)
@@ -632,7 +632,7 @@ static void __kmod_config_free(struct test_config *config)
        config->test_driver = NULL;
 
        kfree_const(config->test_fs);
-       config->test_driver = NULL;
+       config->test_fs = NULL;
 }
 
 static void kmod_config_free(struct kmod_test_device *test_dev)
index 6a8ac76..e52f8ca 100644 (file)
@@ -541,38 +541,45 @@ static unsigned int __init print_ht(struct rhltable *rhlt)
 static int __init test_insert_dup(struct test_obj_rhl *rhl_test_objects,
                                  int cnt, bool slow)
 {
-       struct rhltable rhlt;
+       struct rhltable *rhlt;
        unsigned int i, ret;
        const char *key;
        int err = 0;
 
-       err = rhltable_init(&rhlt, &test_rht_params_dup);
-       if (WARN_ON(err))
+       rhlt = kmalloc(sizeof(*rhlt), GFP_KERNEL);
+       if (WARN_ON(!rhlt))
+               return -EINVAL;
+
+       err = rhltable_init(rhlt, &test_rht_params_dup);
+       if (WARN_ON(err)) {
+               kfree(rhlt);
                return err;
+       }
 
        for (i = 0; i < cnt; i++) {
                rhl_test_objects[i].value.tid = i;
-               key = rht_obj(&rhlt.ht, &rhl_test_objects[i].list_node.rhead);
+               key = rht_obj(&rhlt->ht, &rhl_test_objects[i].list_node.rhead);
                key += test_rht_params_dup.key_offset;
 
                if (slow) {
-                       err = PTR_ERR(rhashtable_insert_slow(&rhlt.ht, key,
+                       err = PTR_ERR(rhashtable_insert_slow(&rhlt->ht, key,
                                                             &rhl_test_objects[i].list_node.rhead));
                        if (err == -EAGAIN)
                                err = 0;
                } else
-                       err = rhltable_insert(&rhlt,
+                       err = rhltable_insert(rhlt,
                                              &rhl_test_objects[i].list_node,
                                              test_rht_params_dup);
                if (WARN(err, "error %d on element %d/%d (%s)\n", err, i, cnt, slow? "slow" : "fast"))
                        goto skip_print;
        }
 
-       ret = print_ht(&rhlt);
+       ret = print_ht(rhlt);
        WARN(ret != cnt, "missing rhltable elements (%d != %d, %s)\n", ret, cnt, slow? "slow" : "fast");
 
 skip_print:
-       rhltable_destroy(&rhlt);
+       rhltable_destroy(rhlt);
+       kfree(rhlt);
 
        return 0;
 }
index 4676c0a..c596a95 100644 (file)
@@ -199,7 +199,7 @@ static noinline void check_xa_mark_1(struct xarray *xa, unsigned long index)
                XA_BUG_ON(xa, xa_store_index(xa, index + 1, GFP_KERNEL));
                xa_set_mark(xa, index + 1, XA_MARK_0);
                XA_BUG_ON(xa, xa_store_index(xa, index + 2, GFP_KERNEL));
-               xa_set_mark(xa, index + 2, XA_MARK_1);
+               xa_set_mark(xa, index + 2, XA_MARK_2);
                XA_BUG_ON(xa, xa_store_index(xa, next, GFP_KERNEL));
                xa_store_order(xa, index, order, xa_mk_index(index),
                                GFP_KERNEL);
@@ -209,8 +209,8 @@ static noinline void check_xa_mark_1(struct xarray *xa, unsigned long index)
                        void *entry;
 
                        XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_0));
-                       XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_1));
-                       XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_2));
+                       XA_BUG_ON(xa, xa_get_mark(xa, i, XA_MARK_1));
+                       XA_BUG_ON(xa, !xa_get_mark(xa, i, XA_MARK_2));
 
                        /* We should see two elements in the array */
                        rcu_read_lock();
@@ -357,7 +357,7 @@ static noinline void check_cmpxchg(struct xarray *xa)
 static noinline void check_reserve(struct xarray *xa)
 {
        void *entry;
-       unsigned long index = 0;
+       unsigned long index;
 
        /* An array with a reserved entry is not empty */
        XA_BUG_ON(xa, !xa_empty(xa));
@@ -382,10 +382,12 @@ static noinline void check_reserve(struct xarray *xa)
        xa_erase_index(xa, 12345678);
        XA_BUG_ON(xa, !xa_empty(xa));
 
-       /* And so does xa_insert */
+       /* But xa_insert does not */
        xa_reserve(xa, 12345678, GFP_KERNEL);
-       XA_BUG_ON(xa, xa_insert(xa, 12345678, xa_mk_value(12345678), 0) != 0);
-       xa_erase_index(xa, 12345678);
+       XA_BUG_ON(xa, xa_insert(xa, 12345678, xa_mk_value(12345678), 0) !=
+                       -EEXIST);
+       XA_BUG_ON(xa, xa_empty(xa));
+       XA_BUG_ON(xa, xa_erase(xa, 12345678) != NULL);
        XA_BUG_ON(xa, !xa_empty(xa));
 
        /* Can iterate through a reserved entry */
@@ -393,7 +395,7 @@ static noinline void check_reserve(struct xarray *xa)
        xa_reserve(xa, 6, GFP_KERNEL);
        xa_store_index(xa, 7, GFP_KERNEL);
 
-       xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) {
+       xa_for_each(xa, index, entry) {
                XA_BUG_ON(xa, index != 5 && index != 7);
        }
        xa_destroy(xa);
@@ -812,17 +814,16 @@ static noinline void check_find_1(struct xarray *xa)
 static noinline void check_find_2(struct xarray *xa)
 {
        void *entry;
-       unsigned long i, j, index = 0;
+       unsigned long i, j, index;
 
-       xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) {
+       xa_for_each(xa, index, entry) {
                XA_BUG_ON(xa, true);
        }
 
        for (i = 0; i < 1024; i++) {
                xa_store_index(xa, index, GFP_KERNEL);
                j = 0;
-               index = 0;
-               xa_for_each(xa, entry, index, ULONG_MAX, XA_PRESENT) {
+               xa_for_each(xa, index, entry) {
                        XA_BUG_ON(xa, xa_mk_index(index) != entry);
                        XA_BUG_ON(xa, index != j++);
                }
@@ -839,6 +840,7 @@ static noinline void check_find_3(struct xarray *xa)
 
        for (i = 0; i < 100; i++) {
                for (j = 0; j < 100; j++) {
+                       rcu_read_lock();
                        for (k = 0; k < 100; k++) {
                                xas_set(&xas, j);
                                xas_for_each_marked(&xas, entry, k, XA_MARK_0)
@@ -847,6 +849,7 @@ static noinline void check_find_3(struct xarray *xa)
                                        XA_BUG_ON(xa,
                                                xas.xa_node != XAS_RESTART);
                        }
+                       rcu_read_unlock();
                }
                xa_store_index(xa, i, GFP_KERNEL);
                xa_set_mark(xa, i, XA_MARK_0);
@@ -1183,6 +1186,35 @@ static noinline void check_store_range(struct xarray *xa)
        }
 }
 
+static void check_align_1(struct xarray *xa, char *name)
+{
+       int i;
+       unsigned int id;
+       unsigned long index;
+       void *entry;
+
+       for (i = 0; i < 8; i++) {
+               id = 0;
+               XA_BUG_ON(xa, xa_alloc(xa, &id, UINT_MAX, name + i, GFP_KERNEL)
+                               != 0);
+               XA_BUG_ON(xa, id != i);
+       }
+       xa_for_each(xa, index, entry)
+               XA_BUG_ON(xa, xa_is_err(entry));
+       xa_destroy(xa);
+}
+
+static noinline void check_align(struct xarray *xa)
+{
+       char name[] = "Motorola 68000";
+
+       check_align_1(xa, name);
+       check_align_1(xa, name + 1);
+       check_align_1(xa, name + 2);
+       check_align_1(xa, name + 3);
+//     check_align_2(xa, name);
+}
+
 static LIST_HEAD(shadow_nodes);
 
 static void test_update_node(struct xa_node *node)
@@ -1332,6 +1364,7 @@ static int xarray_checks(void)
        check_create_range(&array);
        check_store_range(&array);
        check_store_iter(&array);
+       check_align(&xa0);
 
        check_workingset(&array, 0);
        check_workingset(&array, 64);
index 5f3f931..81c3171 100644 (file)
@@ -232,6 +232,8 @@ void *xas_load(struct xa_state *xas)
                if (xas->xa_shift > node->shift)
                        break;
                entry = xas_descend(xas, node);
+               if (node->shift == 0)
+                       break;
        }
        return entry;
 }
@@ -506,7 +508,7 @@ static void xas_free_nodes(struct xa_state *xas, struct xa_node *top)
        for (;;) {
                void *entry = xa_entry_locked(xas->xa, node, offset);
 
-               if (xa_is_node(entry)) {
+               if (node->shift && xa_is_node(entry)) {
                        node = xa_to_node(entry);
                        offset = 0;
                        continue;
@@ -604,6 +606,7 @@ static int xas_expand(struct xa_state *xas, void *head)
 /*
  * xas_create() - Create a slot to store an entry in.
  * @xas: XArray operation state.
+ * @allow_root: %true if we can store the entry in the root directly
  *
  * Most users will not need to call this function directly, as it is called
  * by xas_store().  It is useful for doing conditional store operations
@@ -613,7 +616,7 @@ static int xas_expand(struct xa_state *xas, void *head)
  * If the slot was newly created, returns %NULL.  If it failed to create the
  * slot, returns %NULL and indicates the error in @xas.
  */
-static void *xas_create(struct xa_state *xas)
+static void *xas_create(struct xa_state *xas, bool allow_root)
 {
        struct xarray *xa = xas->xa;
        void *entry;
@@ -628,6 +631,8 @@ static void *xas_create(struct xa_state *xas)
                shift = xas_expand(xas, entry);
                if (shift < 0)
                        return NULL;
+               if (!shift && !allow_root)
+                       shift = XA_CHUNK_SHIFT;
                entry = xa_head_locked(xa);
                slot = &xa->xa_head;
        } else if (xas_error(xas)) {
@@ -687,7 +692,7 @@ void xas_create_range(struct xa_state *xas)
        xas->xa_sibs = 0;
 
        for (;;) {
-               xas_create(xas);
+               xas_create(xas, true);
                if (xas_error(xas))
                        goto restore;
                if (xas->xa_index <= (index | XA_CHUNK_MASK))
@@ -754,7 +759,7 @@ void *xas_store(struct xa_state *xas, void *entry)
        bool value = xa_is_value(entry);
 
        if (entry)
-               first = xas_create(xas);
+               first = xas_create(xas, !xa_is_node(entry));
        else
                first = xas_load(xas);
 
@@ -1250,35 +1255,6 @@ void *xas_find_conflict(struct xa_state *xas)
 }
 EXPORT_SYMBOL_GPL(xas_find_conflict);
 
-/**
- * xa_init_flags() - Initialise an empty XArray with flags.
- * @xa: XArray.
- * @flags: XA_FLAG values.
- *
- * If you need to initialise an XArray with special flags (eg you need
- * to take the lock from interrupt context), use this function instead
- * of xa_init().
- *
- * Context: Any context.
- */
-void xa_init_flags(struct xarray *xa, gfp_t flags)
-{
-       unsigned int lock_type;
-       static struct lock_class_key xa_lock_irq;
-       static struct lock_class_key xa_lock_bh;
-
-       spin_lock_init(&xa->xa_lock);
-       xa->xa_flags = flags;
-       xa->xa_head = NULL;
-
-       lock_type = xa_lock_type(xa);
-       if (lock_type == XA_LOCK_IRQ)
-               lockdep_set_class(&xa->xa_lock, &xa_lock_irq);
-       else if (lock_type == XA_LOCK_BH)
-               lockdep_set_class(&xa->xa_lock, &xa_lock_bh);
-}
-EXPORT_SYMBOL(xa_init_flags);
-
 /**
  * xa_load() - Load an entry from an XArray.
  * @xa: XArray.
@@ -1308,7 +1284,6 @@ static void *xas_result(struct xa_state *xas, void *curr)
 {
        if (xa_is_zero(curr))
                return NULL;
-       XA_NODE_BUG_ON(xas->xa_node, xa_is_internal(curr));
        if (xas_error(xas))
                curr = xas->xa_node;
        return curr;
@@ -1378,7 +1353,7 @@ void *__xa_store(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
        XA_STATE(xas, xa, index);
        void *curr;
 
-       if (WARN_ON_ONCE(xa_is_internal(entry)))
+       if (WARN_ON_ONCE(xa_is_advanced(entry)))
                return XA_ERROR(-EINVAL);
        if (xa_track_free(xa) && !entry)
                entry = XA_ZERO_ENTRY;
@@ -1444,7 +1419,7 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index,
        XA_STATE(xas, xa, index);
        void *curr;
 
-       if (WARN_ON_ONCE(xa_is_internal(entry)))
+       if (WARN_ON_ONCE(xa_is_advanced(entry)))
                return XA_ERROR(-EINVAL);
        if (xa_track_free(xa) && !entry)
                entry = XA_ZERO_ENTRY;
@@ -1464,6 +1439,47 @@ void *__xa_cmpxchg(struct xarray *xa, unsigned long index,
 }
 EXPORT_SYMBOL(__xa_cmpxchg);
 
+/**
+ * __xa_insert() - Store this entry in the XArray if no entry is present.
+ * @xa: XArray.
+ * @index: Index into array.
+ * @entry: New entry.
+ * @gfp: Memory allocation flags.
+ *
+ * Inserting a NULL entry will store a reserved entry (like xa_reserve())
+ * if no entry is present.  Inserting will fail if a reserved entry is
+ * present, even though loading from this index will return NULL.
+ *
+ * Context: Any context.  Expects xa_lock to be held on entry.  May
+ * release and reacquire xa_lock if @gfp flags permit.
+ * Return: 0 if the store succeeded.  -EEXIST if another entry was present.
+ * -ENOMEM if memory could not be allocated.
+ */
+int __xa_insert(struct xarray *xa, unsigned long index, void *entry, gfp_t gfp)
+{
+       XA_STATE(xas, xa, index);
+       void *curr;
+
+       if (WARN_ON_ONCE(xa_is_advanced(entry)))
+               return -EINVAL;
+       if (!entry)
+               entry = XA_ZERO_ENTRY;
+
+       do {
+               curr = xas_load(&xas);
+               if (!curr) {
+                       xas_store(&xas, entry);
+                       if (xa_track_free(xa))
+                               xas_clear_mark(&xas, XA_FREE_MARK);
+               } else {
+                       xas_set_err(&xas, -EEXIST);
+               }
+       } while (__xas_nomem(&xas, gfp));
+
+       return xas_error(&xas);
+}
+EXPORT_SYMBOL(__xa_insert);
+
 /**
  * __xa_reserve() - Reserve this index in the XArray.
  * @xa: XArray.
@@ -1567,7 +1583,7 @@ void *xa_store_range(struct xarray *xa, unsigned long first,
                        if (last + 1)
                                order = __ffs(last + 1);
                        xas_set_order(&xas, last, order);
-                       xas_create(&xas);
+                       xas_create(&xas, true);
                        if (xas_error(&xas))
                                goto unlock;
                }
@@ -1609,7 +1625,7 @@ int __xa_alloc(struct xarray *xa, u32 *id, u32 max, void *entry, gfp_t gfp)
        XA_STATE(xas, xa, 0);
        int err;
 
-       if (WARN_ON_ONCE(xa_is_internal(entry)))
+       if (WARN_ON_ONCE(xa_is_advanced(entry)))
                return -EINVAL;
        if (WARN_ON_ONCE(!xa_track_free(xa)))
                return -EINVAL;
index 8a8bb87..72e6d0c 100644 (file)
@@ -689,6 +689,7 @@ static int cgwb_bdi_init(struct backing_dev_info *bdi)
        INIT_RADIX_TREE(&bdi->cgwb_tree, GFP_ATOMIC);
        bdi->cgwb_congested_tree = RB_ROOT;
        mutex_init(&bdi->cgwb_release_mutex);
+       init_rwsem(&bdi->wb_switch_rwsem);
 
        ret = wb_init(&bdi->wb, bdi, 1, GFP_KERNEL);
        if (!ret) {
index 0abb987..1611cf0 100644 (file)
@@ -44,7 +44,7 @@ const struct trace_print_flags vmaflag_names[] = {
 
 void __dump_page(struct page *page, const char *reason)
 {
-       struct address_space *mapping = page_mapping(page);
+       struct address_space *mapping;
        bool page_poisoned = PagePoisoned(page);
        int mapcount;
 
@@ -58,6 +58,8 @@ void __dump_page(struct page *page, const char *reason)
                goto hex_only;
        }
 
+       mapping = page_mapping(page);
+
        /*
         * Avoid VM_BUG_ON() in page_mapcount().
         * page->_mapcount space in struct page is used by sl[aou]b pages to
index 05acd7e..7502964 100644 (file)
--- a/mm/gup.c
+++ b/mm/gup.c
@@ -1674,7 +1674,8 @@ static int gup_pmd_range(pud_t pud, unsigned long addr, unsigned long end,
                if (!pmd_present(pmd))
                        return 0;
 
-               if (unlikely(pmd_trans_huge(pmd) || pmd_huge(pmd))) {
+               if (unlikely(pmd_trans_huge(pmd) || pmd_huge(pmd) ||
+                            pmd_devmap(pmd))) {
                        /*
                         * NUMA hinting faults need to be handled in the GUP
                         * slowpath for accounting purposes and so that they
index 7450888..afef616 100644 (file)
@@ -3238,7 +3238,6 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
        struct page *ptepage;
        unsigned long addr;
        int cow;
-       struct address_space *mapping = vma->vm_file->f_mapping;
        struct hstate *h = hstate_vma(vma);
        unsigned long sz = huge_page_size(h);
        struct mmu_notifier_range range;
@@ -3250,23 +3249,13 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
                mmu_notifier_range_init(&range, src, vma->vm_start,
                                        vma->vm_end);
                mmu_notifier_invalidate_range_start(&range);
-       } else {
-               /*
-                * For shared mappings i_mmap_rwsem must be held to call
-                * huge_pte_alloc, otherwise the returned ptep could go
-                * away if part of a shared pmd and another thread calls
-                * huge_pmd_unshare.
-                */
-               i_mmap_lock_read(mapping);
        }
 
        for (addr = vma->vm_start; addr < vma->vm_end; addr += sz) {
                spinlock_t *src_ptl, *dst_ptl;
-
                src_pte = huge_pte_offset(src, addr, sz);
                if (!src_pte)
                        continue;
-
                dst_pte = huge_pte_alloc(dst, addr, sz);
                if (!dst_pte) {
                        ret = -ENOMEM;
@@ -3337,8 +3326,6 @@ int copy_hugetlb_page_range(struct mm_struct *dst, struct mm_struct *src,
 
        if (cow)
                mmu_notifier_invalidate_range_end(&range);
-       else
-               i_mmap_unlock_read(mapping);
 
        return ret;
 }
@@ -3755,16 +3742,16 @@ static vm_fault_t hugetlb_no_page(struct mm_struct *mm,
        }
 
        /*
-        * We can not race with truncation due to holding i_mmap_rwsem.
-        * Check once here for faults beyond end of file.
+        * Use page lock to guard against racing truncation
+        * before we get page_table_lock.
         */
-       size = i_size_read(mapping->host) >> huge_page_shift(h);
-       if (idx >= size)
-               goto out;
-
 retry:
        page = find_lock_page(mapping, idx);
        if (!page) {
+               size = i_size_read(mapping->host) >> huge_page_shift(h);
+               if (idx >= size)
+                       goto out;
+
                /*
                 * Check for page in userfault range
                 */
@@ -3784,18 +3771,14 @@ retry:
                        };
 
                        /*
-                        * hugetlb_fault_mutex and i_mmap_rwsem must be
-                        * dropped before handling userfault.  Reacquire
-                        * after handling fault to make calling code simpler.
+                        * hugetlb_fault_mutex must be dropped before
+                        * handling userfault.  Reacquire after handling
+                        * fault to make calling code simpler.
                         */
                        hash = hugetlb_fault_mutex_hash(h, mm, vma, mapping,
                                                        idx, haddr);
                        mutex_unlock(&hugetlb_fault_mutex_table[hash]);
-                       i_mmap_unlock_read(mapping);
-
                        ret = handle_userfault(&vmf, VM_UFFD_MISSING);
-
-                       i_mmap_lock_read(mapping);
                        mutex_lock(&hugetlb_fault_mutex_table[hash]);
                        goto out;
                }
@@ -3854,6 +3837,9 @@ retry:
        }
 
        ptl = huge_pte_lock(h, mm, ptep);
+       size = i_size_read(mapping->host) >> huge_page_shift(h);
+       if (idx >= size)
+               goto backout;
 
        ret = 0;
        if (!huge_pte_none(huge_ptep_get(ptep)))
@@ -3940,11 +3926,6 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
 
        ptep = huge_pte_offset(mm, haddr, huge_page_size(h));
        if (ptep) {
-               /*
-                * Since we hold no locks, ptep could be stale.  That is
-                * OK as we are only making decisions based on content and
-                * not actually modifying content here.
-                */
                entry = huge_ptep_get(ptep);
                if (unlikely(is_hugetlb_entry_migration(entry))) {
                        migration_entry_wait_huge(vma, mm, ptep);
@@ -3952,33 +3933,20 @@ vm_fault_t hugetlb_fault(struct mm_struct *mm, struct vm_area_struct *vma,
                } else if (unlikely(is_hugetlb_entry_hwpoisoned(entry)))
                        return VM_FAULT_HWPOISON_LARGE |
                                VM_FAULT_SET_HINDEX(hstate_index(h));
+       } else {
+               ptep = huge_pte_alloc(mm, haddr, huge_page_size(h));
+               if (!ptep)
+                       return VM_FAULT_OOM;
        }
 
-       /*
-        * Acquire i_mmap_rwsem before calling huge_pte_alloc and hold
-        * until finished with ptep.  This serves two purposes:
-        * 1) It prevents huge_pmd_unshare from being called elsewhere
-        *    and making the ptep no longer valid.
-        * 2) It synchronizes us with file truncation.
-        *
-        * ptep could have already be assigned via huge_pte_offset.  That
-        * is OK, as huge_pte_alloc will return the same value unless
-        * something changed.
-        */
        mapping = vma->vm_file->f_mapping;
-       i_mmap_lock_read(mapping);
-       ptep = huge_pte_alloc(mm, haddr, huge_page_size(h));
-       if (!ptep) {
-               i_mmap_unlock_read(mapping);
-               return VM_FAULT_OOM;
-       }
+       idx = vma_hugecache_offset(h, vma, haddr);
 
        /*
         * Serialize hugepage allocation and instantiation, so that we don't
         * get spurious allocation failures if two CPUs race to instantiate
         * the same page in the page cache.
         */
-       idx = vma_hugecache_offset(h, vma, haddr);
        hash = hugetlb_fault_mutex_hash(h, mm, vma, mapping, idx, haddr);
        mutex_lock(&hugetlb_fault_mutex_table[hash]);
 
@@ -4066,7 +4034,6 @@ out_ptl:
        }
 out_mutex:
        mutex_unlock(&hugetlb_fault_mutex_table[hash]);
-       i_mmap_unlock_read(mapping);
        /*
         * Generally it's safe to hold refcount during waiting page lock. But
         * here we just wait to defer the next page fault to avoid busy loop and
@@ -4301,7 +4268,8 @@ long follow_hugetlb_page(struct mm_struct *mm, struct vm_area_struct *vma,
                                break;
                        }
                        if (ret & VM_FAULT_RETRY) {
-                               if (nonblocking)
+                               if (nonblocking &&
+                                   !(fault_flags & FAULT_FLAG_RETRY_NOWAIT))
                                        *nonblocking = 0;
                                *nr_pages = 0;
                                /*
@@ -4671,12 +4639,10 @@ void adjust_range_if_pmd_sharing_possible(struct vm_area_struct *vma,
  * Search for a shareable pmd page for hugetlb. In any case calls pmd_alloc()
  * and returns the corresponding pte. While this is not necessary for the
  * !shared pmd case because we can allocate the pmd later as well, it makes the
- * code much cleaner.
- *
- * This routine must be called with i_mmap_rwsem held in at least read mode.
- * For hugetlbfs, this prevents removal of any page table entries associated
- * with the address space.  This is important as we are setting up sharing
- * based on existing page table entries (mappings).
+ * code much cleaner. pmd allocation is essential for the shared case because
+ * pud has to be populated inside the same i_mmap_rwsem section - otherwise
+ * racing tasks could either miss the sharing (see huge_pte_offset) or select a
+ * bad pmd for sharing.
  */
 pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
 {
@@ -4693,6 +4659,7 @@ pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
        if (!vma_shareable(vma, addr))
                return (pte_t *)pmd_alloc(mm, pud, addr);
 
+       i_mmap_lock_write(mapping);
        vma_interval_tree_foreach(svma, &mapping->i_mmap, idx, idx) {
                if (svma == vma)
                        continue;
@@ -4722,6 +4689,7 @@ pte_t *huge_pmd_share(struct mm_struct *mm, unsigned long addr, pud_t *pud)
        spin_unlock(ptl);
 out:
        pte = (pte_t *)pmd_alloc(mm, pud, addr);
+       i_mmap_unlock_write(mapping);
        return pte;
 }
 
@@ -4732,7 +4700,7 @@ out:
  * indicated by page_count > 1, unmap is achieved by clearing pud and
  * decrementing the ref count. If count == 1, the pte page is not shared.
  *
- * Called with page table lock held and i_mmap_rwsem held in write mode.
+ * called with page table lock held.
  *
  * returns: 1 successfully unmapped a shared pte page
  *         0 the underlying pte page is not shared, or it is the last user
index 0a14fcf..5d1065e 100644 (file)
@@ -5,7 +5,10 @@ UBSAN_SANITIZE_generic.o := n
 UBSAN_SANITIZE_tags.o := n
 KCOV_INSTRUMENT := n
 
+CFLAGS_REMOVE_common.o = -pg
 CFLAGS_REMOVE_generic.o = -pg
+CFLAGS_REMOVE_tags.o = -pg
+
 # Function splitter causes unnecessary splits in __asan_load1/__asan_store1
 # see: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=63533
 
index 03d5d13..09b534f 100644 (file)
@@ -298,8 +298,6 @@ void kasan_cache_create(struct kmem_cache *cache, unsigned int *size,
                return;
        }
 
-       cache->align = round_up(cache->align, KASAN_SHADOW_SCALE_SIZE);
-
        *flags |= SLAB_KASAN;
 }
 
@@ -349,28 +347,48 @@ void kasan_poison_object_data(struct kmem_cache *cache, void *object)
 }
 
 /*
- * Since it's desirable to only call object contructors once during slab
- * allocation, we preassign tags to all such objects. Also preassign tags for
- * SLAB_TYPESAFE_BY_RCU slabs to avoid use-after-free reports.
- * For SLAB allocator we can't preassign tags randomly since the freelist is
- * stored as an array of indexes instead of a linked list. Assign tags based
- * on objects indexes, so that objects that are next to each other get
- * different tags.
- * After a tag is assigned, the object always gets allocated with the same tag.
- * The reason is that we can't change tags for objects with constructors on
- * reallocation (even for non-SLAB_TYPESAFE_BY_RCU), because the constructor
- * code can save the pointer to the object somewhere (e.g. in the object
- * itself). Then if we retag it, the old saved pointer will become invalid.
+ * This function assigns a tag to an object considering the following:
+ * 1. A cache might have a constructor, which might save a pointer to a slab
+ *    object somewhere (e.g. in the object itself). We preassign a tag for
+ *    each object in caches with constructors during slab creation and reuse
+ *    the same tag each time a particular object is allocated.
+ * 2. A cache might be SLAB_TYPESAFE_BY_RCU, which means objects can be
+ *    accessed after being freed. We preassign tags for objects in these
+ *    caches as well.
+ * 3. For SLAB allocator we can't preassign tags randomly since the freelist
+ *    is stored as an array of indexes instead of a linked list. Assign tags
+ *    based on objects indexes, so that objects that are next to each other
+ *    get different tags.
  */
-static u8 assign_tag(struct kmem_cache *cache, const void *object, bool new)
+static u8 assign_tag(struct kmem_cache *cache, const void *object,
+                       bool init, bool keep_tag)
 {
+       /*
+        * 1. When an object is kmalloc()'ed, two hooks are called:
+        *    kasan_slab_alloc() and kasan_kmalloc(). We assign the
+        *    tag only in the first one.
+        * 2. We reuse the same tag for krealloc'ed objects.
+        */
+       if (keep_tag)
+               return get_tag(object);
+
+       /*
+        * If the cache neither has a constructor nor has SLAB_TYPESAFE_BY_RCU
+        * set, assign a tag when the object is being allocated (init == false).
+        */
        if (!cache->ctor && !(cache->flags & SLAB_TYPESAFE_BY_RCU))
-               return new ? KASAN_TAG_KERNEL : random_tag();
+               return init ? KASAN_TAG_KERNEL : random_tag();
 
+       /* For caches that either have a constructor or SLAB_TYPESAFE_BY_RCU: */
 #ifdef CONFIG_SLAB
+       /* For SLAB assign tags based on the object index in the freelist. */
        return (u8)obj_to_index(cache, virt_to_page(object), (void *)object);
 #else
-       return new ? random_tag() : get_tag(object);
+       /*
+        * For SLUB assign a random tag during slab creation, otherwise reuse
+        * the already assigned tag.
+        */
+       return init ? random_tag() : get_tag(object);
 #endif
 }
 
@@ -386,17 +404,12 @@ void * __must_check kasan_init_slab_obj(struct kmem_cache *cache,
        __memset(alloc_info, 0, sizeof(*alloc_info));
 
        if (IS_ENABLED(CONFIG_KASAN_SW_TAGS))
-               object = set_tag(object, assign_tag(cache, object, true));
+               object = set_tag(object,
+                               assign_tag(cache, object, true, false));
 
        return (void *)object;
 }
 
-void * __must_check kasan_slab_alloc(struct kmem_cache *cache, void *object,
-                                       gfp_t flags)
-{
-       return kasan_kmalloc(cache, object, cache->object_size, flags);
-}
-
 static inline bool shadow_invalid(u8 tag, s8 shadow_byte)
 {
        if (IS_ENABLED(CONFIG_KASAN_GENERIC))
@@ -452,8 +465,8 @@ bool kasan_slab_free(struct kmem_cache *cache, void *object, unsigned long ip)
        return __kasan_slab_free(cache, object, ip, true);
 }
 
-void * __must_check kasan_kmalloc(struct kmem_cache *cache, const void *object,
-                                       size_t size, gfp_t flags)
+static void *__kasan_kmalloc(struct kmem_cache *cache, const void *object,
+                               size_t size, gfp_t flags, bool keep_tag)
 {
        unsigned long redzone_start;
        unsigned long redzone_end;
@@ -471,7 +484,7 @@ void * __must_check kasan_kmalloc(struct kmem_cache *cache, const void *object,
                                KASAN_SHADOW_SCALE_SIZE);
 
        if (IS_ENABLED(CONFIG_KASAN_SW_TAGS))
-               tag = assign_tag(cache, object, false);
+               tag = assign_tag(cache, object, false, keep_tag);
 
        /* Tag is ignored in set_tag without CONFIG_KASAN_SW_TAGS */
        kasan_unpoison_shadow(set_tag(object, tag), size);
@@ -483,6 +496,18 @@ void * __must_check kasan_kmalloc(struct kmem_cache *cache, const void *object,
 
        return set_tag(object, tag);
 }
+
+void * __must_check kasan_slab_alloc(struct kmem_cache *cache, void *object,
+                                       gfp_t flags)
+{
+       return __kasan_kmalloc(cache, object, cache->object_size, flags, false);
+}
+
+void * __must_check kasan_kmalloc(struct kmem_cache *cache, const void *object,
+                               size_t size, gfp_t flags)
+{
+       return __kasan_kmalloc(cache, object, size, flags, true);
+}
 EXPORT_SYMBOL(kasan_kmalloc);
 
 void * __must_check kasan_kmalloc_large(const void *ptr, size_t size,
@@ -522,7 +547,8 @@ void * __must_check kasan_krealloc(const void *object, size_t size, gfp_t flags)
        if (unlikely(!PageSlab(page)))
                return kasan_kmalloc_large(object, size, flags);
        else
-               return kasan_kmalloc(page->slab_cache, object, size, flags);
+               return __kasan_kmalloc(page->slab_cache, object, size,
+                                               flags, true);
 }
 
 void kasan_poison_kfree(void *ptr, unsigned long ip)
index 0777649..63fca31 100644 (file)
@@ -46,7 +46,7 @@ void kasan_init_tags(void)
        int cpu;
 
        for_each_possible_cpu(cpu)
-               per_cpu(prng_state, cpu) = get_random_u32();
+               per_cpu(prng_state, cpu) = (u32)get_cycles();
 }
 
 /*
index f9d9dc2..707fa55 100644 (file)
@@ -574,6 +574,7 @@ static struct kmemleak_object *create_object(unsigned long ptr, size_t size,
        unsigned long flags;
        struct kmemleak_object *object, *parent;
        struct rb_node **link, *rb_parent;
+       unsigned long untagged_ptr;
 
        object = kmem_cache_alloc(object_cache, gfp_kmemleak_mask(gfp));
        if (!object) {
@@ -619,8 +620,9 @@ static struct kmemleak_object *create_object(unsigned long ptr, size_t size,
 
        write_lock_irqsave(&kmemleak_lock, flags);
 
-       min_addr = min(min_addr, ptr);
-       max_addr = max(max_addr, ptr + size);
+       untagged_ptr = (unsigned long)kasan_reset_tag((void *)ptr);
+       min_addr = min(min_addr, untagged_ptr);
+       max_addr = max(max_addr, untagged_ptr + size);
        link = &object_tree_root.rb_node;
        rb_parent = NULL;
        while (*link) {
@@ -1333,6 +1335,7 @@ static void scan_block(void *_start, void *_end,
        unsigned long *start = PTR_ALIGN(_start, BYTES_PER_POINTER);
        unsigned long *end = _end - (BYTES_PER_POINTER - 1);
        unsigned long flags;
+       unsigned long untagged_ptr;
 
        read_lock_irqsave(&kmemleak_lock, flags);
        for (ptr = start; ptr < end; ptr++) {
@@ -1347,7 +1350,8 @@ static void scan_block(void *_start, void *_end,
                pointer = *ptr;
                kasan_enable_current();
 
-               if (pointer < min_addr || pointer >= max_addr)
+               untagged_ptr = (unsigned long)kasan_reset_tag((void *)pointer);
+               if (untagged_ptr < min_addr || untagged_ptr >= max_addr)
                        continue;
 
                /*
index 022d4cb..ea31045 100644 (file)
 
 #include "internal.h"
 
+#define INIT_MEMBLOCK_REGIONS                  128
+#define INIT_PHYSMEM_REGIONS                   4
+
+#ifndef INIT_MEMBLOCK_RESERVED_REGIONS
+# define INIT_MEMBLOCK_RESERVED_REGIONS                INIT_MEMBLOCK_REGIONS
+#endif
+
 /**
  * DOC: memblock overview
  *
@@ -92,7 +99,7 @@ unsigned long max_pfn;
 unsigned long long max_possible_pfn;
 
 static struct memblock_region memblock_memory_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
-static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_REGIONS] __initdata_memblock;
+static struct memblock_region memblock_reserved_init_regions[INIT_MEMBLOCK_RESERVED_REGIONS] __initdata_memblock;
 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
 static struct memblock_region memblock_physmem_init_regions[INIT_PHYSMEM_REGIONS] __initdata_memblock;
 #endif
@@ -105,7 +112,7 @@ struct memblock memblock __initdata_memblock = {
 
        .reserved.regions       = memblock_reserved_init_regions,
        .reserved.cnt           = 1,    /* empty dummy entry */
-       .reserved.max           = INIT_MEMBLOCK_REGIONS,
+       .reserved.max           = INIT_MEMBLOCK_RESERVED_REGIONS,
        .reserved.name          = "reserved",
 
 #ifdef CONFIG_HAVE_MEMBLOCK_PHYS_MAP
index 6379fff..831be5f 100644 (file)
@@ -372,7 +372,8 @@ static void kill_procs(struct list_head *to_kill, int forcekill, bool fail,
                        if (fail || tk->addr_valid == 0) {
                                pr_err("Memory failure: %#lx: forcibly killing %s:%d because of failure to unmap corrupted page\n",
                                       pfn, tk->tsk->comm, tk->tsk->pid);
-                               force_sig(SIGKILL, tk->tsk);
+                               do_send_sig_info(SIGKILL, SEND_SIG_PRIV,
+                                                tk->tsk, PIDTYPE_PID);
                        }
 
                        /*
@@ -966,7 +967,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
        enum ttu_flags ttu = TTU_IGNORE_MLOCK | TTU_IGNORE_ACCESS;
        struct address_space *mapping;
        LIST_HEAD(tokill);
-       bool unmap_success = true;
+       bool unmap_success;
        int kill = 1, forcekill;
        struct page *hpage = *hpagep;
        bool mlocked = PageMlocked(hpage);
@@ -1028,19 +1029,7 @@ static bool hwpoison_user_mappings(struct page *p, unsigned long pfn,
        if (kill)
                collect_procs(hpage, &tokill, flags & MF_ACTION_REQUIRED);
 
-       if (!PageHuge(hpage)) {
-               unmap_success = try_to_unmap(hpage, ttu);
-       } else if (mapping) {
-               /*
-                * For hugetlb pages, try_to_unmap could potentially call
-                * huge_pmd_unshare.  Because of this, take semaphore in
-                * write mode here and set TTU_RMAP_LOCKED to indicate we
-                * have taken the lock at this higer level.
-                */
-               i_mmap_lock_write(mapping);
-               unmap_success = try_to_unmap(hpage, ttu|TTU_RMAP_LOCKED);
-               i_mmap_unlock_write(mapping);
-       }
+       unmap_success = try_to_unmap(hpage, ttu);
        if (!unmap_success)
                pr_err("Memory failure: %#lx: failed to unmap page (mapcount=%d)\n",
                       pfn, page_mapcount(hpage));
index a52663c..e11ca9d 100644 (file)
@@ -2994,6 +2994,28 @@ static vm_fault_t __do_fault(struct vm_fault *vmf)
        struct vm_area_struct *vma = vmf->vma;
        vm_fault_t ret;
 
+       /*
+        * Preallocate pte before we take page_lock because this might lead to
+        * deadlocks for memcg reclaim which waits for pages under writeback:
+        *                              lock_page(A)
+        *                              SetPageWriteback(A)
+        *                              unlock_page(A)
+        * lock_page(B)
+        *                              lock_page(B)
+        * pte_alloc_pne
+        *   shrink_page_list
+        *     wait_on_page_writeback(A)
+        *                              SetPageWriteback(B)
+        *                              unlock_page(B)
+        *                              # flush A, B to clear the writeback
+        */
+       if (pmd_none(*vmf->pmd) && !vmf->prealloc_pte) {
+               vmf->prealloc_pte = pte_alloc_one(vmf->vma->vm_mm);
+               if (!vmf->prealloc_pte)
+                       return VM_FAULT_OOM;
+               smp_wmb(); /* See comment in __pte_alloc() */
+       }
+
        ret = vma->vm_ops->fault(vmf);
        if (unlikely(ret & (VM_FAULT_ERROR | VM_FAULT_NOPAGE | VM_FAULT_RETRY |
                            VM_FAULT_DONE_COW)))
@@ -4077,8 +4099,8 @@ static int __follow_pte_pmd(struct mm_struct *mm, unsigned long address,
                goto out;
 
        if (range) {
-               range->start = address & PAGE_MASK;
-               range->end = range->start + PAGE_SIZE;
+               mmu_notifier_range_init(range, mm, address & PAGE_MASK,
+                                    (address & PAGE_MASK) + PAGE_SIZE);
                mmu_notifier_invalidate_range_start(range);
        }
        ptep = pte_offset_map_lock(mm, pmd, address, ptlp);
index b9a667d..1ad2832 100644 (file)
@@ -1188,11 +1188,13 @@ static inline int pageblock_free(struct page *page)
        return PageBuddy(page) && page_order(page) >= pageblock_order;
 }
 
-/* Return the start of the next active pageblock after a given page */
-static struct page *next_active_pageblock(struct page *page)
+/* Return the pfn of the start of the next active pageblock after a given pfn */
+static unsigned long next_active_pageblock(unsigned long pfn)
 {
+       struct page *page = pfn_to_page(pfn);
+
        /* Ensure the starting page is pageblock-aligned */
-       BUG_ON(page_to_pfn(page) & (pageblock_nr_pages - 1));
+       BUG_ON(pfn & (pageblock_nr_pages - 1));
 
        /* If the entire pageblock is free, move to the end of free page */
        if (pageblock_free(page)) {
@@ -1200,16 +1202,16 @@ static struct page *next_active_pageblock(struct page *page)
                /* be careful. we don't have locks, page_order can be changed.*/
                order = page_order(page);
                if ((order < MAX_ORDER) && (order >= pageblock_order))
-                       return page + (1 << order);
+                       return pfn + (1 << order);
        }
 
-       return page + pageblock_nr_pages;
+       return pfn + pageblock_nr_pages;
 }
 
-static bool is_pageblock_removable_nolock(struct page *page)
+static bool is_pageblock_removable_nolock(unsigned long pfn)
 {
+       struct page *page = pfn_to_page(pfn);
        struct zone *zone;
-       unsigned long pfn;
 
        /*
         * We have to be careful here because we are iterating over memory
@@ -1232,12 +1234,14 @@ static bool is_pageblock_removable_nolock(struct page *page)
 /* Checks if this range of memory is likely to be hot-removable. */
 bool is_mem_section_removable(unsigned long start_pfn, unsigned long nr_pages)
 {
-       struct page *page = pfn_to_page(start_pfn);
-       struct page *end_page = page + nr_pages;
+       unsigned long end_pfn, pfn;
+
+       end_pfn = min(start_pfn + nr_pages,
+                       zone_end_pfn(page_zone(pfn_to_page(start_pfn))));
 
        /* Check the starting page of each pageblock within the range */
-       for (; page < end_page; page = next_active_pageblock(page)) {
-               if (!is_pageblock_removable_nolock(page))
+       for (pfn = start_pfn; pfn < end_pfn; pfn = next_active_pageblock(pfn)) {
+               if (!is_pageblock_removable_nolock(pfn))
                        return false;
                cond_resched();
        }
@@ -1273,6 +1277,9 @@ int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
                                i++;
                        if (i == MAX_ORDER_NR_PAGES || pfn + i >= end_pfn)
                                continue;
+                       /* Check if we got outside of the zone */
+                       if (zone && !zone_spans_pfn(zone, pfn + i))
+                               return 0;
                        page = pfn_to_page(pfn + i);
                        if (zone && page_zone(page) != zone)
                                return 0;
@@ -1301,23 +1308,27 @@ int test_pages_in_a_zone(unsigned long start_pfn, unsigned long end_pfn,
 static unsigned long scan_movable_pages(unsigned long start, unsigned long end)
 {
        unsigned long pfn;
-       struct page *page;
+
        for (pfn = start; pfn < end; pfn++) {
-               if (pfn_valid(pfn)) {
-                       page = pfn_to_page(pfn);
-                       if (PageLRU(page))
-                               return pfn;
-                       if (__PageMovable(page))
-                               return pfn;
-                       if (PageHuge(page)) {
-                               if (hugepage_migration_supported(page_hstate(page)) &&
-                                   page_huge_active(page))
-                                       return pfn;
-                               else
-                                       pfn = round_up(pfn + 1,
-                                               1 << compound_order(page)) - 1;
-                       }
-               }
+               struct page *page, *head;
+               unsigned long skip;
+
+               if (!pfn_valid(pfn))
+                       continue;
+               page = pfn_to_page(pfn);
+               if (PageLRU(page))
+                       return pfn;
+               if (__PageMovable(page))
+                       return pfn;
+
+               if (!PageHuge(page))
+                       continue;
+               head = compound_head(page);
+               if (hugepage_migration_supported(page_hstate(head)) &&
+                   page_huge_active(head))
+                       return pfn;
+               skip = (1 << compound_order(head)) - (page - head);
+               pfn += skip - 1;
        }
        return 0;
 }
@@ -1344,7 +1355,6 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
 {
        unsigned long pfn;
        struct page *page;
-       int not_managed = 0;
        int ret = 0;
        LIST_HEAD(source);
 
@@ -1392,7 +1402,6 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                else
                        ret = isolate_movable_page(page, ISOLATE_UNEVICTABLE);
                if (!ret) { /* Success */
-                       put_page(page);
                        list_add_tail(&page->lru, &source);
                        if (!__PageMovable(page))
                                inc_node_page_state(page, NR_ISOLATED_ANON +
@@ -1401,22 +1410,10 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                } else {
                        pr_warn("failed to isolate pfn %lx\n", pfn);
                        dump_page(page, "isolation failed");
-                       put_page(page);
-                       /* Because we don't have big zone->lock. we should
-                          check this again here. */
-                       if (page_count(page)) {
-                               not_managed++;
-                               ret = -EBUSY;
-                               break;
-                       }
                }
+               put_page(page);
        }
        if (!list_empty(&source)) {
-               if (not_managed) {
-                       putback_movable_pages(&source);
-                       goto out;
-               }
-
                /* Allocate a new page from the nearest neighbor node */
                ret = migrate_pages(&source, new_node_page, NULL, 0,
                                        MIGRATE_SYNC, MR_MEMORY_HOTPLUG);
@@ -1429,7 +1426,7 @@ do_migrate_range(unsigned long start_pfn, unsigned long end_pfn)
                        putback_movable_pages(&source);
                }
        }
-out:
+
        return ret;
 }
 
@@ -1576,7 +1573,6 @@ static int __ref __offline_pages(unsigned long start_pfn,
           we assume this for now. .*/
        if (!test_pages_in_a_zone(start_pfn, end_pfn, &valid_start,
                                  &valid_end)) {
-               mem_hotplug_done();
                ret = -EINVAL;
                reason = "multizone range";
                goto failed_removal;
@@ -1591,7 +1587,6 @@ static int __ref __offline_pages(unsigned long start_pfn,
                                       MIGRATE_MOVABLE,
                                       SKIP_HWPOISON | REPORT_FAILURE);
        if (ret) {
-               mem_hotplug_done();
                reason = "failure to isolate range";
                goto failed_removal;
        }
index d4496d9..ee2bce5 100644 (file)
@@ -1314,7 +1314,7 @@ static int copy_nodes_to_user(unsigned long __user *mask, unsigned long maxnode,
                              nodemask_t *nodes)
 {
        unsigned long copy = ALIGN(maxnode-1, 64) / 8;
-       const int nbytes = BITS_TO_LONGS(MAX_NUMNODES) * sizeof(long);
+       unsigned int nbytes = BITS_TO_LONGS(nr_node_ids) * sizeof(long);
 
        if (copy > nbytes) {
                if (copy > PAGE_SIZE)
@@ -1491,7 +1491,7 @@ static int kernel_get_mempolicy(int __user *policy,
        int uninitialized_var(pval);
        nodemask_t nodes;
 
-       if (nmask != NULL && maxnode < MAX_NUMNODES)
+       if (nmask != NULL && maxnode < nr_node_ids)
                return -EINVAL;
 
        err = do_get_mempolicy(&pval, &nodes, addr, flags);
@@ -1527,7 +1527,7 @@ COMPAT_SYSCALL_DEFINE5(get_mempolicy, int __user *, policy,
        unsigned long nr_bits, alloc_size;
        DECLARE_BITMAP(bm, MAX_NUMNODES);
 
-       nr_bits = min_t(unsigned long, maxnode-1, MAX_NUMNODES);
+       nr_bits = min_t(unsigned long, maxnode-1, nr_node_ids);
        alloc_size = ALIGN(nr_bits, BITS_PER_LONG) / 8;
 
        if (nmask)
index ccf8966..d4fd680 100644 (file)
@@ -709,7 +709,6 @@ static bool buffer_migrate_lock_buffers(struct buffer_head *head,
        /* Simple case, sync compaction */
        if (mode != MIGRATE_ASYNC) {
                do {
-                       get_bh(bh);
                        lock_buffer(bh);
                        bh = bh->b_this_page;
 
@@ -720,18 +719,15 @@ static bool buffer_migrate_lock_buffers(struct buffer_head *head,
 
        /* async case, we cannot block on lock_buffer so use trylock_buffer */
        do {
-               get_bh(bh);
                if (!trylock_buffer(bh)) {
                        /*
                         * We failed to lock the buffer and cannot stall in
                         * async migration. Release the taken locks
                         */
                        struct buffer_head *failed_bh = bh;
-                       put_bh(failed_bh);
                        bh = head;
                        while (bh != failed_bh) {
                                unlock_buffer(bh);
-                               put_bh(bh);
                                bh = bh->b_this_page;
                        }
                        return false;
@@ -818,7 +814,6 @@ unlock_buffers:
        bh = head;
        do {
                unlock_buffer(bh);
-               put_bh(bh);
                bh = bh->b_this_page;
 
        } while (bh != head);
@@ -1135,10 +1130,13 @@ out:
         * If migration is successful, decrease refcount of the newpage
         * which will not free the page because new page owner increased
         * refcounter. As well, if it is LRU page, add the page to LRU
-        * list in here.
+        * list in here. Use the old state of the isolated source page to
+        * determine if we migrated a LRU page. newpage was already unlocked
+        * and possibly modified by its owner - don't rely on the page
+        * state.
         */
        if (rc == MIGRATEPAGE_SUCCESS) {
-               if (unlikely(__PageMovable(newpage)))
+               if (unlikely(!is_lru))
                        put_page(newpage);
                else
                        putback_lru_page(newpage);
@@ -1324,19 +1322,8 @@ static int unmap_and_move_huge_page(new_page_t get_new_page,
                goto put_anon;
 
        if (page_mapped(hpage)) {
-               struct address_space *mapping = page_mapping(hpage);
-
-               /*
-                * try_to_unmap could potentially call huge_pmd_unshare.
-                * Because of this, take semaphore in write mode here and
-                * set TTU_RMAP_LOCKED to let lower levels know we have
-                * taken the lock.
-                */
-               i_mmap_lock_write(mapping);
                try_to_unmap(hpage,
-                       TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS|
-                       TTU_RMAP_LOCKED);
-               i_mmap_unlock_write(mapping);
+                       TTU_MIGRATION|TTU_IGNORE_MLOCK|TTU_IGNORE_ACCESS);
                page_was_mapped = 1;
        }
 
index f0f9146..218099b 100644 (file)
@@ -42,14 +42,72 @@ static int mincore_hugetlb(pte_t *pte, unsigned long hmask, unsigned long addr,
        return 0;
 }
 
-static int mincore_unmapped_range(unsigned long addr, unsigned long end,
-                                  struct mm_walk *walk)
+/*
+ * Later we can get more picky about what "in core" means precisely.
+ * For now, simply check to see if the page is in the page cache,
+ * and is up to date; i.e. that no page-in operation would be required
+ * at this time if an application were to map and access this page.
+ */
+static unsigned char mincore_page(struct address_space *mapping, pgoff_t pgoff)
+{
+       unsigned char present = 0;
+       struct page *page;
+
+       /*
+        * When tmpfs swaps out a page from a file, any process mapping that
+        * file will not get a swp_entry_t in its pte, but rather it is like
+        * any other file mapping (ie. marked !present and faulted in with
+        * tmpfs's .fault). So swapped out tmpfs mappings are tested here.
+        */
+#ifdef CONFIG_SWAP
+       if (shmem_mapping(mapping)) {
+               page = find_get_entry(mapping, pgoff);
+               /*
+                * shmem/tmpfs may return swap: account for swapcache
+                * page too.
+                */
+               if (xa_is_value(page)) {
+                       swp_entry_t swp = radix_to_swp_entry(page);
+                       page = find_get_page(swap_address_space(swp),
+                                            swp_offset(swp));
+               }
+       } else
+               page = find_get_page(mapping, pgoff);
+#else
+       page = find_get_page(mapping, pgoff);
+#endif
+       if (page) {
+               present = PageUptodate(page);
+               put_page(page);
+       }
+
+       return present;
+}
+
+static int __mincore_unmapped_range(unsigned long addr, unsigned long end,
+                               struct vm_area_struct *vma, unsigned char *vec)
 {
-       unsigned char *vec = walk->private;
        unsigned long nr = (end - addr) >> PAGE_SHIFT;
+       int i;
 
-       memset(vec, 0, nr);
-       walk->private += nr;
+       if (vma->vm_file) {
+               pgoff_t pgoff;
+
+               pgoff = linear_page_index(vma, addr);
+               for (i = 0; i < nr; i++, pgoff++)
+                       vec[i] = mincore_page(vma->vm_file->f_mapping, pgoff);
+       } else {
+               for (i = 0; i < nr; i++)
+                       vec[i] = 0;
+       }
+       return nr;
+}
+
+static int mincore_unmapped_range(unsigned long addr, unsigned long end,
+                                  struct mm_walk *walk)
+{
+       walk->private += __mincore_unmapped_range(addr, end,
+                                                 walk->vma, walk->private);
        return 0;
 }
 
@@ -69,9 +127,8 @@ static int mincore_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
                goto out;
        }
 
-       /* We'll consider a THP page under construction to be there */
        if (pmd_trans_unstable(pmd)) {
-               memset(vec, 1, nr);
+               __mincore_unmapped_range(addr, end, vma, vec);
                goto out;
        }
 
@@ -80,17 +137,28 @@ static int mincore_pte_range(pmd_t *pmd, unsigned long addr, unsigned long end,
                pte_t pte = *ptep;
 
                if (pte_none(pte))
-                       *vec = 0;
+                       __mincore_unmapped_range(addr, addr + PAGE_SIZE,
+                                                vma, vec);
                else if (pte_present(pte))
                        *vec = 1;
                else { /* pte is a swap entry */
                        swp_entry_t entry = pte_to_swp_entry(pte);
 
-                       /*
-                        * migration or hwpoison entries are always
-                        * uptodate
-                        */
-                       *vec = !!non_swap_entry(entry);
+                       if (non_swap_entry(entry)) {
+                               /*
+                                * migration or hwpoison entries are always
+                                * uptodate
+                                */
+                               *vec = 1;
+                       } else {
+#ifdef CONFIG_SWAP
+                               *vec = mincore_page(swap_address_space(entry),
+                                                   swp_offset(entry));
+#else
+                               WARN_ON(1);
+                               *vec = 1;
+#endif
+                       }
                }
                vec++;
        }
index f0e8cd9..26ea863 100644 (file)
@@ -647,8 +647,8 @@ static int oom_reaper(void *unused)
 
 static void wake_oom_reaper(struct task_struct *tsk)
 {
-       /* tsk is already queued? */
-       if (tsk == oom_reaper_list || tsk->oom_reaper_list)
+       /* mm is already queued? */
+       if (test_and_set_bit(MMF_OOM_REAP_QUEUED, &tsk->signal->oom_mm->flags))
                return;
 
        get_task_struct(tsk);
@@ -975,6 +975,13 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
         * still freeing memory.
         */
        read_lock(&tasklist_lock);
+
+       /*
+        * The task 'p' might have already exited before reaching here. The
+        * put_task_struct() will free task_struct 'p' while the loop still try
+        * to access the field of 'p', so, get an extra reference.
+        */
+       get_task_struct(p);
        for_each_thread(p, t) {
                list_for_each_entry(child, &t->children, sibling) {
                        unsigned int child_points;
@@ -994,6 +1001,7 @@ static void oom_kill_process(struct oom_control *oc, const char *message)
                        }
                }
        }
+       put_task_struct(p);
        read_unlock(&tasklist_lock);
 
        /*
index cde5dac..0b9f577 100644 (file)
@@ -2170,6 +2170,18 @@ static inline void boost_watermark(struct zone *zone)
 
        max_boost = mult_frac(zone->_watermark[WMARK_HIGH],
                        watermark_boost_factor, 10000);
+
+       /*
+        * high watermark may be uninitialised if fragmentation occurs
+        * very early in boot so do not boost. We do not fall
+        * through and boost by pageblock_nr_pages as failing
+        * allocations that early means that reclaim is not going
+        * to help and it may even be impossible to reclaim the
+        * boosted watermark resulting in a hang.
+        */
+       if (!max_boost)
+               return;
+
        max_boost = max(pageblock_nr_pages, max_boost);
 
        zone->watermark_boost = min(zone->watermark_boost + pageblock_nr_pages,
@@ -2214,7 +2226,7 @@ static void steal_suitable_fallback(struct zone *zone, struct page *page,
         */
        boost_watermark(zone);
        if (alloc_flags & ALLOC_KSWAPD)
-               wakeup_kswapd(zone, 0, 0, zone_idx(zone));
+               set_bit(ZONE_BOOSTED_WATERMARK, &zone->flags);
 
        /* We are not allowed to try stealing from the whole block */
        if (!whole_block)
@@ -3102,6 +3114,12 @@ struct page *rmqueue(struct zone *preferred_zone,
        local_irq_restore(flags);
 
 out:
+       /* Separate test+clear to avoid unnecessary atomics */
+       if (test_bit(ZONE_BOOSTED_WATERMARK, &zone->flags)) {
+               clear_bit(ZONE_BOOSTED_WATERMARK, &zone->flags);
+               wakeup_kswapd(zone, 0, 0, zone_idx(zone));
+       }
+
        VM_BUG_ON_PAGE(page && bad_range(zone, page), page);
        return page;
 
@@ -4669,11 +4687,11 @@ refill:
                /* Even if we own the page, we do not use atomic_set().
                 * This would break get_page_unless_zero() users.
                 */
-               page_ref_add(page, size - 1);
+               page_ref_add(page, PAGE_FRAG_CACHE_MAX_SIZE);
 
                /* reset page count bias and offset to start of new frag */
                nc->pfmemalloc = page_is_pfmemalloc(page);
-               nc->pagecnt_bias = size;
+               nc->pagecnt_bias = PAGE_FRAG_CACHE_MAX_SIZE + 1;
                nc->offset = size;
        }
 
@@ -4689,10 +4707,10 @@ refill:
                size = nc->size;
 #endif
                /* OK, page count is 0, we can safely set it */
-               set_page_count(page, size);
+               set_page_count(page, PAGE_FRAG_CACHE_MAX_SIZE + 1);
 
                /* reset page count bias and offset to start of new frag */
-               nc->pagecnt_bias = size;
+               nc->pagecnt_bias = PAGE_FRAG_CACHE_MAX_SIZE + 1;
                offset = size - fragsz;
        }
 
@@ -5695,18 +5713,6 @@ void __meminit memmap_init_zone(unsigned long size, int nid, unsigned long zone,
                        cond_resched();
                }
        }
-#ifdef CONFIG_SPARSEMEM
-       /*
-        * If the zone does not span the rest of the section then
-        * we should at least initialize those pages. Otherwise we
-        * could blow up on a poisoned page in some paths which depend
-        * on full sections being initialized (e.g. memory hotplug).
-        */
-       while (end_pfn % PAGES_PER_SECTION) {
-               __init_single_page(pfn_to_page(end_pfn), end_pfn, zone, nid);
-               end_pfn++;
-       }
-#endif
 }
 
 #ifdef CONFIG_ZONE_DEVICE
index ae44f7a..8c78b8d 100644 (file)
@@ -398,10 +398,8 @@ void __init page_ext_init(void)
                         * We know some arch can have a nodes layout such as
                         * -------------pfn-------------->
                         * N0 | N1 | N2 | N0 | N1 | N2|....
-                        *
-                        * Take into account DEFERRED_STRUCT_PAGE_INIT.
                         */
-                       if (early_pfn_to_nid(pfn) != nid)
+                       if (pfn_to_nid(pfn) != nid)
                                continue;
                        if (init_section_page_ext(pfn, nid))
                                goto oom;
index 21a26cf..0454ecc 100644 (file)
--- a/mm/rmap.c
+++ b/mm/rmap.c
@@ -25,7 +25,6 @@
  *     page->flags PG_locked (lock_page)
  *       hugetlbfs_i_mmap_rwsem_key (in huge_pmd_share)
  *         mapping->i_mmap_rwsem
- *           hugetlb_fault_mutex (hugetlbfs specific page fault mutex)
  *           anon_vma->rwsem
  *             mm->page_table_lock or pte_lock
  *               zone_lru_lock (in mark_page_accessed, isolate_lru_page)
@@ -1372,16 +1371,13 @@ static bool try_to_unmap_one(struct page *page, struct vm_area_struct *vma,
         * Note that the page can not be free in this function as call of
         * try_to_unmap() must hold a reference on the page.
         */
-       mmu_notifier_range_init(&range, vma->vm_mm, vma->vm_start,
-                               min(vma->vm_end, vma->vm_start +
+       mmu_notifier_range_init(&range, vma->vm_mm, address,
+                               min(vma->vm_end, address +
                                    (PAGE_SIZE << compound_order(page))));
        if (PageHuge(page)) {
                /*
                 * If sharing is possible, start and end will be adjusted
                 * accordingly.
-                *
-                * If called for a huge page, caller must hold i_mmap_rwsem
-                * in write mode as it is possible to call huge_pmd_unshare.
                 */
                adjust_range_if_pmd_sharing_possible(vma, &range.start,
                                                     &range.end);
index 6ece1e2..0905215 100644 (file)
@@ -2854,10 +2854,14 @@ static int shmem_link(struct dentry *old_dentry, struct inode *dir, struct dentr
         * No ordinary (disk based) filesystem counts links as inodes;
         * but each new link needs a new dentry, pinning lowmem, and
         * tmpfs dentries cannot be pruned until they are unlinked.
+        * But if an O_TMPFILE file is linked into the tmpfs, the
+        * first link must skip that, to get the accounting right.
         */
-       ret = shmem_reserve_inode(inode->i_sb);
-       if (ret)
-               goto out;
+       if (inode->i_nlink) {
+               ret = shmem_reserve_inode(inode->i_sb);
+               if (ret)
+                       goto out;
+       }
 
        dir->i_size += BOGO_DIRENT_SIZE;
        inode->i_ctime = dir->i_ctime = dir->i_mtime = current_time(inode);
index 73fe23e..91c1863 100644 (file)
--- a/mm/slab.c
+++ b/mm/slab.c
@@ -666,8 +666,10 @@ static struct alien_cache *__alloc_alien_cache(int node, int entries,
        struct alien_cache *alc = NULL;
 
        alc = kmalloc_node(memsize, gfp, node);
-       init_arraycache(&alc->ac, entries, batch);
-       spin_lock_init(&alc->lock);
+       if (alc) {
+               init_arraycache(&alc->ac, entries, batch);
+               spin_lock_init(&alc->lock);
+       }
        return alc;
 }
 
@@ -2357,7 +2359,7 @@ static void *alloc_slabmgmt(struct kmem_cache *cachep,
        void *freelist;
        void *addr = page_address(page);
 
-       page->s_mem = kasan_reset_tag(addr) + colour_off;
+       page->s_mem = addr + colour_off;
        page->active = 0;
 
        if (OBJFREELIST_SLAB(cachep))
@@ -2366,6 +2368,7 @@ static void *alloc_slabmgmt(struct kmem_cache *cachep,
                /* Slab management obj is off-slab. */
                freelist = kmem_cache_alloc_node(cachep->freelist_cache,
                                              local_flags, nodeid);
+               freelist = kasan_reset_tag(freelist);
                if (!freelist)
                        return NULL;
        } else {
@@ -2679,6 +2682,13 @@ static struct page *cache_grow_begin(struct kmem_cache *cachep,
 
        offset *= cachep->colour_off;
 
+       /*
+        * Call kasan_poison_slab() before calling alloc_slabmgmt(), so
+        * page_address() in the latter returns a non-tagged pointer,
+        * as it should be for slab pages.
+        */
+       kasan_poison_slab(page);
+
        /* Get slab management. */
        freelist = alloc_slabmgmt(cachep, page, offset,
                        local_flags & ~GFP_CONSTRAINT_MASK, page_node);
@@ -2687,7 +2697,6 @@ static struct page *cache_grow_begin(struct kmem_cache *cachep,
 
        slab_map_pages(cachep, page, freelist);
 
-       kasan_poison_slab(page);
        cache_init_objs(cachep, page);
 
        if (gfpflags_allow_blocking(local_flags))
@@ -3538,7 +3547,6 @@ void *kmem_cache_alloc(struct kmem_cache *cachep, gfp_t flags)
 {
        void *ret = slab_alloc(cachep, flags, _RET_IP_);
 
-       ret = kasan_slab_alloc(cachep, ret, flags);
        trace_kmem_cache_alloc(_RET_IP_, ret,
                               cachep->object_size, cachep->size, flags);
 
@@ -3628,7 +3636,6 @@ void *kmem_cache_alloc_node(struct kmem_cache *cachep, gfp_t flags, int nodeid)
 {
        void *ret = slab_alloc_node(cachep, flags, nodeid, _RET_IP_);
 
-       ret = kasan_slab_alloc(cachep, ret, flags);
        trace_kmem_cache_alloc_node(_RET_IP_, ret,
                                    cachep->object_size, cachep->size,
                                    flags, nodeid);
@@ -4406,6 +4413,8 @@ void __check_heap_object(const void *ptr, unsigned long n, struct page *page,
        unsigned int objnr;
        unsigned long offset;
 
+       ptr = kasan_reset_tag(ptr);
+
        /* Find and validate object. */
        cachep = page->slab_cache;
        objnr = obj_to_index(cachep, page, (void *)ptr);
index 4190c24..3841053 100644 (file)
--- a/mm/slab.h
+++ b/mm/slab.h
@@ -437,11 +437,10 @@ static inline void slab_post_alloc_hook(struct kmem_cache *s, gfp_t flags,
 
        flags &= gfp_allowed_mask;
        for (i = 0; i < size; i++) {
-               void *object = p[i];
-
-               kmemleak_alloc_recursive(object, s->object_size, 1,
+               p[i] = kasan_slab_alloc(s, p[i], flags);
+               /* As p[i] might get tagged, call kmemleak hook after KASAN. */
+               kmemleak_alloc_recursive(p[i], s->object_size, 1,
                                         s->flags, flags);
-               p[i] = kasan_slab_alloc(s, object, flags);
        }
 
        if (memcg_kmem_enabled())
index 81732d0..f9d89c1 100644 (file)
@@ -1228,8 +1228,9 @@ void *kmalloc_order(size_t size, gfp_t flags, unsigned int order)
        flags |= __GFP_COMP;
        page = alloc_pages(flags, order);
        ret = page ? page_address(page) : NULL;
-       kmemleak_alloc(ret, size, 1, flags);
        ret = kasan_kmalloc_large(ret, size, flags);
+       /* As ret might get tagged, call kmemleak hook after KASAN. */
+       kmemleak_alloc(ret, size, 1, flags);
        return ret;
 }
 EXPORT_SYMBOL(kmalloc_order);
index 36c0bef..dc77776 100644 (file)
--- a/mm/slub.c
+++ b/mm/slub.c
@@ -249,7 +249,18 @@ static inline void *freelist_ptr(const struct kmem_cache *s, void *ptr,
                                 unsigned long ptr_addr)
 {
 #ifdef CONFIG_SLAB_FREELIST_HARDENED
-       return (void *)((unsigned long)ptr ^ s->random ^ ptr_addr);
+       /*
+        * When CONFIG_KASAN_SW_TAGS is enabled, ptr_addr might be tagged.
+        * Normally, this doesn't cause any issues, as both set_freepointer()
+        * and get_freepointer() are called with a pointer with the same tag.
+        * However, there are some issues with CONFIG_SLUB_DEBUG code. For
+        * example, when __free_slub() iterates over objects in a cache, it
+        * passes untagged pointers to check_object(). check_object() in turns
+        * calls get_freepointer() with an untagged pointer, which causes the
+        * freepointer to be restored incorrectly.
+        */
+       return (void *)((unsigned long)ptr ^ s->random ^
+                       (unsigned long)kasan_reset_tag((void *)ptr_addr));
 #else
        return ptr;
 #endif
@@ -303,15 +314,10 @@ static inline void set_freepointer(struct kmem_cache *s, void *object, void *fp)
                __p < (__addr) + (__objects) * (__s)->size; \
                __p += (__s)->size)
 
-#define for_each_object_idx(__p, __idx, __s, __addr, __objects) \
-       for (__p = fixup_red_left(__s, __addr), __idx = 1; \
-               __idx <= __objects; \
-               __p += (__s)->size, __idx++)
-
 /* Determine object index from a given position */
 static inline unsigned int slab_index(void *p, struct kmem_cache *s, void *addr)
 {
-       return (p - addr) / s->size;
+       return (kasan_reset_tag(p) - addr) / s->size;
 }
 
 static inline unsigned int order_objects(unsigned int order, unsigned int size)
@@ -507,6 +513,7 @@ static inline int check_valid_pointer(struct kmem_cache *s,
                return 1;
 
        base = page_address(page);
+       object = kasan_reset_tag(object);
        object = restore_red_left(s, object);
        if (object < base || object >= base + page->objects * s->size ||
                (object - base) % s->size) {
@@ -1075,6 +1082,16 @@ static void setup_object_debug(struct kmem_cache *s, struct page *page,
        init_tracking(s, object);
 }
 
+static void setup_page_debug(struct kmem_cache *s, void *addr, int order)
+{
+       if (!(s->flags & SLAB_POISON))
+               return;
+
+       metadata_access_enable();
+       memset(addr, POISON_INUSE, PAGE_SIZE << order);
+       metadata_access_disable();
+}
+
 static inline int alloc_consistency_checks(struct kmem_cache *s,
                                        struct page *page,
                                        void *object, unsigned long addr)
@@ -1330,6 +1347,8 @@ slab_flags_t kmem_cache_flags(unsigned int object_size,
 #else /* !CONFIG_SLUB_DEBUG */
 static inline void setup_object_debug(struct kmem_cache *s,
                        struct page *page, void *object) {}
+static inline void setup_page_debug(struct kmem_cache *s,
+                       void *addr, int order) {}
 
 static inline int alloc_debug_processing(struct kmem_cache *s,
        struct page *page, void *object, unsigned long addr) { return 0; }
@@ -1374,8 +1393,10 @@ static inline void dec_slabs_node(struct kmem_cache *s, int node,
  */
 static inline void *kmalloc_large_node_hook(void *ptr, size_t size, gfp_t flags)
 {
+       ptr = kasan_kmalloc_large(ptr, size, flags);
+       /* As ptr might get tagged, call kmemleak hook after KASAN. */
        kmemleak_alloc(ptr, size, 1, flags);
-       return kasan_kmalloc_large(ptr, size, flags);
+       return ptr;
 }
 
 static __always_inline void kfree_hook(void *x)
@@ -1641,27 +1662,25 @@ static struct page *allocate_slab(struct kmem_cache *s, gfp_t flags, int node)
        if (page_is_pfmemalloc(page))
                SetPageSlabPfmemalloc(page);
 
-       start = page_address(page);
+       kasan_poison_slab(page);
 
-       if (unlikely(s->flags & SLAB_POISON))
-               memset(start, POISON_INUSE, PAGE_SIZE << order);
+       start = page_address(page);
 
-       kasan_poison_slab(page);
+       setup_page_debug(s, start, order);
 
        shuffle = shuffle_freelist(s, page);
 
        if (!shuffle) {
-               for_each_object_idx(p, idx, s, start, page->objects) {
-                       if (likely(idx < page->objects)) {
-                               next = p + s->size;
-                               next = setup_object(s, page, next);
-                               set_freepointer(s, p, next);
-                       } else
-                               set_freepointer(s, p, NULL);
-               }
                start = fixup_red_left(s, start);
                start = setup_object(s, page, start);
                page->freelist = start;
+               for (idx = 0, p = start; idx < page->objects - 1; idx++) {
+                       next = p + s->size;
+                       next = setup_object(s, page, next);
+                       set_freepointer(s, p, next);
+                       p = next;
+               }
+               set_freepointer(s, p, NULL);
        }
 
        page->inuse = page->objects;
@@ -3846,6 +3865,8 @@ void __check_heap_object(const void *ptr, unsigned long n, struct page *page,
        unsigned int offset;
        size_t object_size;
 
+       ptr = kasan_reset_tag(ptr);
+
        /* Find object and usable object size. */
        s = page->slab_cache;
 
index 4929bc1..4d7d37e 100644 (file)
--- a/mm/swap.c
+++ b/mm/swap.c
@@ -320,11 +320,6 @@ static inline void activate_page_drain(int cpu)
 {
 }
 
-static bool need_activate_page_drain(int cpu)
-{
-       return false;
-}
-
 void activate_page(struct page *page)
 {
        struct zone *zone = page_zone(page);
@@ -653,13 +648,15 @@ void lru_add_drain(void)
        put_cpu();
 }
 
+#ifdef CONFIG_SMP
+
+static DEFINE_PER_CPU(struct work_struct, lru_add_drain_work);
+
 static void lru_add_drain_per_cpu(struct work_struct *dummy)
 {
        lru_add_drain();
 }
 
-static DEFINE_PER_CPU(struct work_struct, lru_add_drain_work);
-
 /*
  * Doesn't need any cpu hotplug locking because we do rely on per-cpu
  * kworkers being shut down before our page_alloc_cpu_dead callback is
@@ -702,6 +699,12 @@ void lru_add_drain_all(void)
 
        mutex_unlock(&lock);
 }
+#else
+void lru_add_drain_all(void)
+{
+       lru_add_drain();
+}
+#endif
 
 /**
  * release_pages - batched put_page()
index 852eb4e..14faadc 100644 (file)
@@ -247,7 +247,8 @@ static DEFINE_STATIC_KEY_FALSE_RO(bypass_usercopy_checks);
 /*
  * Validates that the given object is:
  * - not bogus address
- * - known-safe heap or stack object
+ * - fully contained by stack (or stack frame, when available)
+ * - fully within SLAB object (or object whitelist area, when available)
  * - not in kernel text
  */
 void __check_object_size(const void *ptr, unsigned long n, bool to_user)
@@ -262,9 +263,6 @@ void __check_object_size(const void *ptr, unsigned long n, bool to_user)
        /* Check for invalid addresses. */
        check_bogus_address((const unsigned long)ptr, n, to_user);
 
-       /* Check for bad heap object. */
-       check_heap_object(ptr, n, to_user);
-
        /* Check for bad stack object. */
        switch (check_stack_object(ptr, n)) {
        case NOT_STACK:
@@ -282,6 +280,9 @@ void __check_object_size(const void *ptr, unsigned long n, bool to_user)
                usercopy_abort("process stack", NULL, to_user, 0, n);
        }
 
+       /* Check for bad heap object. */
+       check_heap_object(ptr, n, to_user);
+
        /* Check for object in kernel to avoid text exposure. */
        check_kernel_text_object((const unsigned long)ptr, n, to_user);
 }
index 065c1ce..d59b5a7 100644 (file)
@@ -267,14 +267,10 @@ retry:
                VM_BUG_ON(dst_addr & ~huge_page_mask(h));
 
                /*
-                * Serialize via i_mmap_rwsem and hugetlb_fault_mutex.
-                * i_mmap_rwsem ensures the dst_pte remains valid even
-                * in the case of shared pmds.  fault mutex prevents
-                * races with other faulting threads.
+                * Serialize via hugetlb_fault_mutex
                 */
-               mapping = dst_vma->vm_file->f_mapping;
-               i_mmap_lock_read(mapping);
                idx = linear_page_index(dst_vma, dst_addr);
+               mapping = dst_vma->vm_file->f_mapping;
                hash = hugetlb_fault_mutex_hash(h, dst_mm, dst_vma, mapping,
                                                                idx, dst_addr);
                mutex_lock(&hugetlb_fault_mutex_table[hash]);
@@ -283,7 +279,6 @@ retry:
                dst_pte = huge_pte_alloc(dst_mm, dst_addr, huge_page_size(h));
                if (!dst_pte) {
                        mutex_unlock(&hugetlb_fault_mutex_table[hash]);
-                       i_mmap_unlock_read(mapping);
                        goto out_unlock;
                }
 
@@ -291,7 +286,6 @@ retry:
                dst_pteval = huge_ptep_get(dst_pte);
                if (!huge_pte_none(dst_pteval)) {
                        mutex_unlock(&hugetlb_fault_mutex_table[hash]);
-                       i_mmap_unlock_read(mapping);
                        goto out_unlock;
                }
 
@@ -299,7 +293,6 @@ retry:
                                                dst_addr, src_addr, &page);
 
                mutex_unlock(&hugetlb_fault_mutex_table[hash]);
-               i_mmap_unlock_read(mapping);
                vm_alloc_shared = vm_shared;
 
                cond_resched();
index 4df23d6..379319b 100644 (file)
--- a/mm/util.c
+++ b/mm/util.c
@@ -150,7 +150,7 @@ void *memdup_user(const void __user *src, size_t len)
 {
        void *p;
 
-       p = kmalloc_track_caller(len, GFP_USER);
+       p = kmalloc_track_caller(len, GFP_USER | __GFP_NOWARN);
        if (!p)
                return ERR_PTR(-ENOMEM);
 
@@ -478,7 +478,7 @@ bool page_mapped(struct page *page)
                return true;
        if (PageHuge(page))
                return false;
-       for (i = 0; i < hpage_nr_pages(page); i++) {
+       for (i = 0; i < (1 << compound_order(page)); i++) {
                if (atomic_read(&page[i]._mapcount) >= 0)
                        return true;
        }
index a714c4f..e979705 100644 (file)
@@ -491,16 +491,6 @@ static unsigned long do_shrink_slab(struct shrink_control *shrinkctl,
                delta = freeable / 2;
        }
 
-       /*
-        * Make sure we apply some minimal pressure on default priority
-        * even on small cgroups. Stale objects are not only consuming memory
-        * by themselves, but can also hold a reference to a dying cgroup,
-        * preventing it from being reclaimed. A dying cgroup with all
-        * corresponding structures like per-cpu stats and kmem caches
-        * can be really big, so it may lead to a significant waste of memory.
-        */
-       delta = max_t(unsigned long long, delta, min(freeable, batch_size));
-
        total_scan += delta;
        if (total_scan < 0) {
                pr_err("shrink_slab: %pF negative objects to delete nr=%ld\n",
index 70417e9..314bbc8 100644 (file)
@@ -114,6 +114,7 @@ netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
        dst = (ax25_address *)(bp + 1);
        src = (ax25_address *)(bp + 8);
 
+       ax25_route_lock_use();
        route = ax25_get_route(dst, NULL);
        if (route) {
                digipeat = route->digipeat;
@@ -206,9 +207,8 @@ netdev_tx_t ax25_ip_xmit(struct sk_buff *skb)
        ax25_queue_xmit(skb, dev);
 
 put:
-       if (route)
-               ax25_put_route(route);
 
+       ax25_route_lock_unuse();
        return NETDEV_TX_OK;
 }
 
index a0eff32..66f74c8 100644 (file)
@@ -40,7 +40,7 @@
 #include <linux/export.h>
 
 static ax25_route *ax25_route_list;
-static DEFINE_RWLOCK(ax25_route_lock);
+DEFINE_RWLOCK(ax25_route_lock);
 
 void ax25_rt_device_down(struct net_device *dev)
 {
@@ -335,6 +335,7 @@ const struct seq_operations ax25_rt_seqops = {
  *     Find AX.25 route
  *
  *     Only routes with a reference count of zero can be destroyed.
+ *     Must be called with ax25_route_lock read locked.
  */
 ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
 {
@@ -342,7 +343,6 @@ ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
        ax25_route *ax25_def_rt = NULL;
        ax25_route *ax25_rt;
 
-       read_lock(&ax25_route_lock);
        /*
         *      Bind to the physical interface we heard them on, or the default
         *      route if none is found;
@@ -365,11 +365,6 @@ ax25_route *ax25_get_route(ax25_address *addr, struct net_device *dev)
        if (ax25_spe_rt != NULL)
                ax25_rt = ax25_spe_rt;
 
-       if (ax25_rt != NULL)
-               ax25_hold_route(ax25_rt);
-
-       read_unlock(&ax25_route_lock);
-
        return ax25_rt;
 }
 
@@ -400,9 +395,12 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
        ax25_route *ax25_rt;
        int err = 0;
 
-       if ((ax25_rt = ax25_get_route(addr, NULL)) == NULL)
+       ax25_route_lock_use();
+       ax25_rt = ax25_get_route(addr, NULL);
+       if (!ax25_rt) {
+               ax25_route_lock_unuse();
                return -EHOSTUNREACH;
-
+       }
        if ((ax25->ax25_dev = ax25_dev_ax25dev(ax25_rt->dev)) == NULL) {
                err = -EHOSTUNREACH;
                goto put;
@@ -437,8 +435,7 @@ int ax25_rt_autobind(ax25_cb *ax25, ax25_address *addr)
        }
 
 put:
-       ax25_put_route(ax25_rt);
-
+       ax25_route_lock_unuse();
        return err;
 }
 
index e8090f0..ef0dec2 100644 (file)
@@ -104,6 +104,9 @@ static u32 batadv_v_elp_get_throughput(struct batadv_hardif_neigh_node *neigh)
 
                ret = cfg80211_get_station(real_netdev, neigh->addr, &sinfo);
 
+               /* free the TID stats immediately */
+               cfg80211_sinfo_release_content(&sinfo);
+
                dev_put(real_netdev);
                if (ret == -ENOENT) {
                        /* Node is not associated anymore! It would be
index 508f441..415d494 100644 (file)
@@ -20,7 +20,6 @@
 #include "main.h"
 
 #include <linux/atomic.h>
-#include <linux/bug.h>
 #include <linux/byteorder/generic.h>
 #include <linux/errno.h>
 #include <linux/gfp.h>
@@ -179,8 +178,10 @@ static bool batadv_is_on_batman_iface(const struct net_device *net_dev)
        parent_dev = __dev_get_by_index((struct net *)parent_net,
                                        dev_get_iflink(net_dev));
        /* if we got a NULL parent_dev there is something broken.. */
-       if (WARN(!parent_dev, "Cannot find parent device"))
+       if (!parent_dev) {
+               pr_err("Cannot find parent device\n");
                return false;
+       }
 
        if (batadv_mutual_parents(net_dev, net, parent_dev, parent_net))
                return false;
index 5db5a0a..ffc83be 100644 (file)
@@ -221,10 +221,14 @@ static netdev_tx_t batadv_interface_tx(struct sk_buff *skb,
 
        netif_trans_update(soft_iface);
        vid = batadv_get_vid(skb, 0);
+
+       skb_reset_mac_header(skb);
        ethhdr = eth_hdr(skb);
 
        switch (ntohs(ethhdr->h_proto)) {
        case ETH_P_8021Q:
+               if (!pskb_may_pull(skb, sizeof(*vhdr)))
+                       goto dropped;
                vhdr = vlan_eth_hdr(skb);
 
                /* drop batman-in-batman packets to prevent loops */
index fa2644d..e31e1b2 100644 (file)
 #include <net/sock.h>
 #include <net/tcp.h>
 
-static __always_inline u32 bpf_test_run_one(struct bpf_prog *prog, void *ctx,
-               struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE])
-{
-       u32 ret;
-
-       preempt_disable();
-       rcu_read_lock();
-       bpf_cgroup_storage_set(storage);
-       ret = BPF_PROG_RUN(prog, ctx);
-       rcu_read_unlock();
-       preempt_enable();
-
-       return ret;
-}
-
-static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat, u32 *ret,
-                       u32 *time)
+static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat,
+                       u32 *retval, u32 *time)
 {
        struct bpf_cgroup_storage *storage[MAX_BPF_CGROUP_STORAGE_TYPE] = { 0 };
        enum bpf_cgroup_storage_type stype;
        u64 time_start, time_spent = 0;
+       int ret = 0;
        u32 i;
 
        for_each_cgroup_storage_type(stype) {
@@ -48,25 +34,42 @@ static int bpf_test_run(struct bpf_prog *prog, void *ctx, u32 repeat, u32 *ret,
 
        if (!repeat)
                repeat = 1;
+
+       rcu_read_lock();
+       preempt_disable();
        time_start = ktime_get_ns();
        for (i = 0; i < repeat; i++) {
-               *ret = bpf_test_run_one(prog, ctx, storage);
+               bpf_cgroup_storage_set(storage);
+               *retval = BPF_PROG_RUN(prog, ctx);
+
+               if (signal_pending(current)) {
+                       ret = -EINTR;
+                       break;
+               }
+
                if (need_resched()) {
-                       if (signal_pending(current))
-                               break;
                        time_spent += ktime_get_ns() - time_start;
+                       preempt_enable();
+                       rcu_read_unlock();
+
                        cond_resched();
+
+                       rcu_read_lock();
+                       preempt_disable();
                        time_start = ktime_get_ns();
                }
        }
        time_spent += ktime_get_ns() - time_start;
+       preempt_enable();
+       rcu_read_unlock();
+
        do_div(time_spent, repeat);
        *time = time_spent > U32_MAX ? U32_MAX : (u32)time_spent;
 
        for_each_cgroup_storage_type(stype)
                bpf_cgroup_storage_free(storage[stype]);
 
-       return 0;
+       return ret;
 }
 
 static int bpf_test_finish(const union bpf_attr *kattr,
index 7acfc83..7ee4fea 100644 (file)
 extern char bpfilter_umh_start;
 extern char bpfilter_umh_end;
 
-static struct umh_info info;
-/* since ip_getsockopt() can run in parallel, serialize access to umh */
-static DEFINE_MUTEX(bpfilter_lock);
-
-static void shutdown_umh(struct umh_info *info)
+static void shutdown_umh(void)
 {
        struct task_struct *tsk;
 
-       if (!info->pid)
+       if (bpfilter_ops.stop)
                return;
-       tsk = get_pid_task(find_vpid(info->pid), PIDTYPE_PID);
+
+       tsk = get_pid_task(find_vpid(bpfilter_ops.info.pid), PIDTYPE_PID);
        if (tsk) {
                force_sig(SIGKILL, tsk);
                put_task_struct(tsk);
        }
-       fput(info->pipe_to_umh);
-       fput(info->pipe_from_umh);
-       info->pid = 0;
 }
 
 static void __stop_umh(void)
 {
-       if (IS_ENABLED(CONFIG_INET)) {
-               bpfilter_process_sockopt = NULL;
-               shutdown_umh(&info);
-       }
-}
-
-static void stop_umh(void)
-{
-       mutex_lock(&bpfilter_lock);
-       __stop_umh();
-       mutex_unlock(&bpfilter_lock);
+       if (IS_ENABLED(CONFIG_INET))
+               shutdown_umh();
 }
 
 static int __bpfilter_process_sockopt(struct sock *sk, int optname,
@@ -63,10 +48,10 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
        req.cmd = optname;
        req.addr = (long __force __user)optval;
        req.len = optlen;
-       mutex_lock(&bpfilter_lock);
-       if (!info.pid)
+       if (!bpfilter_ops.info.pid)
                goto out;
-       n = __kernel_write(info.pipe_to_umh, &req, sizeof(req), &pos);
+       n = __kernel_write(bpfilter_ops.info.pipe_to_umh, &req, sizeof(req),
+                          &pos);
        if (n != sizeof(req)) {
                pr_err("write fail %zd\n", n);
                __stop_umh();
@@ -74,7 +59,8 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
                goto out;
        }
        pos = 0;
-       n = kernel_read(info.pipe_from_umh, &reply, sizeof(reply), &pos);
+       n = kernel_read(bpfilter_ops.info.pipe_from_umh, &reply, sizeof(reply),
+                       &pos);
        if (n != sizeof(reply)) {
                pr_err("read fail %zd\n", n);
                __stop_umh();
@@ -83,37 +69,59 @@ static int __bpfilter_process_sockopt(struct sock *sk, int optname,
        }
        ret = reply.status;
 out:
-       mutex_unlock(&bpfilter_lock);
        return ret;
 }
 
-static int __init load_umh(void)
+static int start_umh(void)
 {
        int err;
 
        /* fork usermode process */
-       info.cmdline = "bpfilter_umh";
        err = fork_usermode_blob(&bpfilter_umh_start,
                                 &bpfilter_umh_end - &bpfilter_umh_start,
-                                &info);
+                                &bpfilter_ops.info);
        if (err)
                return err;
-       pr_info("Loaded bpfilter_umh pid %d\n", info.pid);
+       bpfilter_ops.stop = false;
+       pr_info("Loaded bpfilter_umh pid %d\n", bpfilter_ops.info.pid);
 
        /* health check that usermode process started correctly */
        if (__bpfilter_process_sockopt(NULL, 0, NULL, 0, 0) != 0) {
-               stop_umh();
+               shutdown_umh();
                return -EFAULT;
        }
-       if (IS_ENABLED(CONFIG_INET))
-               bpfilter_process_sockopt = &__bpfilter_process_sockopt;
 
        return 0;
 }
 
+static int __init load_umh(void)
+{
+       int err;
+
+       mutex_lock(&bpfilter_ops.lock);
+       if (!bpfilter_ops.stop) {
+               err = -EFAULT;
+               goto out;
+       }
+       err = start_umh();
+       if (!err && IS_ENABLED(CONFIG_INET)) {
+               bpfilter_ops.sockopt = &__bpfilter_process_sockopt;
+               bpfilter_ops.start = &start_umh;
+       }
+out:
+       mutex_unlock(&bpfilter_ops.lock);
+       return err;
+}
+
 static void __exit fini_umh(void)
 {
-       stop_umh();
+       mutex_lock(&bpfilter_ops.lock);
+       if (IS_ENABLED(CONFIG_INET)) {
+               shutdown_umh();
+               bpfilter_ops.start = NULL;
+               bpfilter_ops.sockopt = NULL;
+       }
+       mutex_unlock(&bpfilter_ops.lock);
 }
 module_init(load_umh);
 module_exit(fini_umh);
index 40311d1..9ea6100 100644 (file)
@@ -1,5 +1,5 @@
 /* SPDX-License-Identifier: GPL-2.0 */
-       .section .init.rodata, "a"
+       .section .rodata, "a"
        .global bpfilter_umh_start
 bpfilter_umh_start:
        .incbin "net/bpfilter/bpfilter_umh"
index fe3c758..9e14767 100644 (file)
@@ -1128,6 +1128,8 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
                        err = -ENOMEM;
                        goto err_unlock;
                }
+               if (swdev_notify)
+                       fdb->added_by_user = 1;
                fdb->added_by_external_learn = 1;
                fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
        } else {
@@ -1147,6 +1149,9 @@ int br_fdb_external_learn_add(struct net_bridge *br, struct net_bridge_port *p,
                        modified = true;
                }
 
+               if (swdev_notify)
+                       fdb->added_by_user = 1;
+
                if (modified)
                        fdb_notify(br, fdb, RTM_NEWNEIGH, swdev_notify);
        }
index 5372e20..48ddc60 100644 (file)
@@ -36,10 +36,10 @@ static inline int should_deliver(const struct net_bridge_port *p,
 
 int br_dev_queue_push_xmit(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+       skb_push(skb, ETH_HLEN);
        if (!is_skb_forwardable(skb->dev, skb))
                goto drop;
 
-       skb_push(skb, ETH_HLEN);
        br_drop_fake_rtable(skb);
 
        if (skb->ip_summed == CHECKSUM_PARTIAL &&
@@ -65,6 +65,7 @@ EXPORT_SYMBOL_GPL(br_dev_queue_push_xmit);
 
 int br_forward_finish(struct net *net, struct sock *sk, struct sk_buff *skb)
 {
+       skb->tstamp = 0;
        return NF_HOOK(NFPROTO_BRIDGE, NF_BR_POST_ROUTING,
                       net, sk, skb, NULL, skb->dev,
                       br_dev_queue_push_xmit);
@@ -97,12 +98,11 @@ static void __br_forward(const struct net_bridge_port *to,
                net = dev_net(indev);
        } else {
                if (unlikely(netpoll_tx_running(to->br->dev))) {
-                       if (!is_skb_forwardable(skb->dev, skb)) {
+                       skb_push(skb, ETH_HLEN);
+                       if (!is_skb_forwardable(skb->dev, skb))
                                kfree_skb(skb);
-                       } else {
-                               skb_push(skb, ETH_HLEN);
+                       else
                                br_netpoll_send_skb(to, skb);
-                       }
                        return;
                }
                br_hook = NF_BR_LOCAL_OUT;
index 3aeff08..ac92b2e 100644 (file)
@@ -1204,14 +1204,7 @@ static void br_multicast_query_received(struct net_bridge *br,
                return;
 
        br_multicast_update_query_timer(br, query, max_delay);
-
-       /* Based on RFC4541, section 2.1.1 IGMP Forwarding Rules,
-        * the arrival port for IGMP Queries where the source address
-        * is 0.0.0.0 should not be added to router port list.
-        */
-       if ((saddr->proto == htons(ETH_P_IP) && saddr->u.ip4) ||
-           saddr->proto == htons(ETH_P_IPV6))
-               br_multicast_mark_router(br, port);
+       br_multicast_mark_router(br, port);
 }
 
 static void br_ip4_multicast_query(struct net_bridge *br,
index d21a236..c93c35b 100644 (file)
@@ -265,7 +265,7 @@ int br_nf_pre_routing_finish_bridge(struct net *net, struct sock *sk, struct sk_
                struct nf_bridge_info *nf_bridge = nf_bridge_info_get(skb);
                int ret;
 
-               if (neigh->hh.hh_len) {
+               if ((neigh->nud_state & NUD_CONNECTED) && neigh->hh.hh_len) {
                        neigh_hh_bridge(&neigh->hh, skb);
                        skb->dev = nf_bridge->physindev;
                        ret = br_handle_frame_finish(net, sk, skb);
index 94039f5..564710f 100644 (file)
@@ -131,6 +131,7 @@ int br_validate_ipv6(struct net *net, struct sk_buff *skb)
                                        IPSTATS_MIB_INDISCARDS);
                        goto drop;
                }
+               hdr = ipv6_hdr(skb);
        }
        if (hdr->nexthdr == NEXTHDR_HOP && br_nf_check_hbh_len(skb))
                goto drop;
index d240b3e..eabf8bf 100644 (file)
@@ -107,6 +107,7 @@ struct br_tunnel_info {
 /* private vlan flags */
 enum {
        BR_VLFLAG_PER_PORT_STATS = BIT(0),
+       BR_VLFLAG_ADDED_BY_SWITCHDEV = BIT(1),
 };
 
 /**
index 4a2f311..96abf8f 100644 (file)
@@ -80,16 +80,18 @@ static bool __vlan_add_flags(struct net_bridge_vlan *v, u16 flags)
 }
 
 static int __vlan_vid_add(struct net_device *dev, struct net_bridge *br,
-                         u16 vid, u16 flags, struct netlink_ext_ack *extack)
+                         struct net_bridge_vlan *v, u16 flags,
+                         struct netlink_ext_ack *extack)
 {
        int err;
 
        /* Try switchdev op first. In case it is not supported, fallback to
         * 8021q add.
         */
-       err = br_switchdev_port_vlan_add(dev, vid, flags, extack);
+       err = br_switchdev_port_vlan_add(dev, v->vid, flags, extack);
        if (err == -EOPNOTSUPP)
-               return vlan_vid_add(dev, br->vlan_proto, vid);
+               return vlan_vid_add(dev, br->vlan_proto, v->vid);
+       v->priv_flags |= BR_VLFLAG_ADDED_BY_SWITCHDEV;
        return err;
 }
 
@@ -121,19 +123,17 @@ static void __vlan_del_list(struct net_bridge_vlan *v)
 }
 
 static int __vlan_vid_del(struct net_device *dev, struct net_bridge *br,
-                         u16 vid)
+                         const struct net_bridge_vlan *v)
 {
        int err;
 
        /* Try switchdev op first. In case it is not supported, fallback to
         * 8021q del.
         */
-       err = br_switchdev_port_vlan_del(dev, vid);
-       if (err == -EOPNOTSUPP) {
-               vlan_vid_del(dev, br->vlan_proto, vid);
-               return 0;
-       }
-       return err;
+       err = br_switchdev_port_vlan_del(dev, v->vid);
+       if (!(v->priv_flags & BR_VLFLAG_ADDED_BY_SWITCHDEV))
+               vlan_vid_del(dev, br->vlan_proto, v->vid);
+       return err == -EOPNOTSUPP ? 0 : err;
 }
 
 /* Returns a master vlan, if it didn't exist it gets created. In all cases a
@@ -242,7 +242,7 @@ static int __vlan_add(struct net_bridge_vlan *v, u16 flags,
                 * This ensures tagged traffic enters the bridge when
                 * promiscuous mode is disabled by br_manage_promisc().
                 */
-               err = __vlan_vid_add(dev, br, v->vid, flags, extack);
+               err = __vlan_vid_add(dev, br, v, flags, extack);
                if (err)
                        goto out;
 
@@ -305,7 +305,7 @@ out_fdb_insert:
 
 out_filt:
        if (p) {
-               __vlan_vid_del(dev, br, v->vid);
+               __vlan_vid_del(dev, br, v);
                if (masterv) {
                        if (v->stats && masterv->stats != v->stats)
                                free_percpu(v->stats);
@@ -338,7 +338,7 @@ static int __vlan_del(struct net_bridge_vlan *v)
 
        __vlan_delete_pvid(vg, v->vid);
        if (p) {
-               err = __vlan_vid_del(p->dev, p->br, v->vid);
+               err = __vlan_vid_del(p->dev, p->br, v);
                if (err)
                        goto out;
        } else {
index 4918287..6693e20 100644 (file)
@@ -1137,14 +1137,16 @@ static int do_replace(struct net *net, const void __user *user,
        tmp.name[sizeof(tmp.name) - 1] = 0;
 
        countersize = COUNTER_OFFSET(tmp.nentries) * nr_cpu_ids;
-       newinfo = vmalloc(sizeof(*newinfo) + countersize);
+       newinfo = __vmalloc(sizeof(*newinfo) + countersize, GFP_KERNEL_ACCOUNT,
+                           PAGE_KERNEL);
        if (!newinfo)
                return -ENOMEM;
 
        if (countersize)
                memset(newinfo->counters, 0, countersize);
 
-       newinfo->entries = vmalloc(tmp.entries_size);
+       newinfo->entries = __vmalloc(tmp.entries_size, GFP_KERNEL_ACCOUNT,
+                                    PAGE_KERNEL);
        if (!newinfo->entries) {
                ret = -ENOMEM;
                goto free_newinfo;
@@ -2291,9 +2293,12 @@ static int compat_do_replace(struct net *net, void __user *user,
 
        xt_compat_lock(NFPROTO_BRIDGE);
 
-       ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries);
-       if (ret < 0)
-               goto out_unlock;
+       if (tmp.nentries) {
+               ret = xt_compat_init_offsets(NFPROTO_BRIDGE, tmp.nentries);
+               if (ret < 0)
+                       goto out_unlock;
+       }
+
        ret = compat_copy_entries(entries_tmp, tmp.entries_size, &state);
        if (ret < 0)
                goto out_unlock;
index 08cbed7..419e8ed 100644 (file)
@@ -229,6 +229,7 @@ static bool reject6_br_csum_ok(struct sk_buff *skb, int hook)
            pskb_trim_rcsum(skb, ntohs(ip6h->payload_len) + sizeof(*ip6h)))
                return false;
 
+       ip6h = ipv6_hdr(skb);
        thoff = ipv6_skip_exthdr(skb, ((u8*)(ip6h+1) - skb->data), &proto, &fo);
        if (thoff < 0 || thoff >= skb->len || (fo & htons(~0x7)) != 0)
                return false;
index 0af8f0d..79bb8af 100644 (file)
@@ -67,6 +67,9 @@
  */
 #define MAX_NFRAMES 256
 
+/* limit timers to 400 days for sending/timeouts */
+#define BCM_TIMER_SEC_MAX (400 * 24 * 60 * 60)
+
 /* use of last_frames[index].flags */
 #define RX_RECV    0x40 /* received data for this element */
 #define RX_THR     0x80 /* element not been sent due to throttle feature */
@@ -140,6 +143,22 @@ static inline ktime_t bcm_timeval_to_ktime(struct bcm_timeval tv)
        return ktime_set(tv.tv_sec, tv.tv_usec * NSEC_PER_USEC);
 }
 
+/* check limitations for timeval provided by user */
+static bool bcm_is_invalid_tv(struct bcm_msg_head *msg_head)
+{
+       if ((msg_head->ival1.tv_sec < 0) ||
+           (msg_head->ival1.tv_sec > BCM_TIMER_SEC_MAX) ||
+           (msg_head->ival1.tv_usec < 0) ||
+           (msg_head->ival1.tv_usec >= USEC_PER_SEC) ||
+           (msg_head->ival2.tv_sec < 0) ||
+           (msg_head->ival2.tv_sec > BCM_TIMER_SEC_MAX) ||
+           (msg_head->ival2.tv_usec < 0) ||
+           (msg_head->ival2.tv_usec >= USEC_PER_SEC))
+               return true;
+
+       return false;
+}
+
 #define CFSIZ(flags) ((flags & CAN_FD_FRAME) ? CANFD_MTU : CAN_MTU)
 #define OPSIZ sizeof(struct bcm_op)
 #define MHSIZ sizeof(struct bcm_msg_head)
@@ -873,6 +892,10 @@ static int bcm_tx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
        if (msg_head->nframes < 1 || msg_head->nframes > MAX_NFRAMES)
                return -EINVAL;
 
+       /* check timeval limitations */
+       if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head))
+               return -EINVAL;
+
        /* check the given can_id */
        op = bcm_find_op(&bo->tx_ops, msg_head, ifindex);
        if (op) {
@@ -1053,6 +1076,10 @@ static int bcm_rx_setup(struct bcm_msg_head *msg_head, struct msghdr *msg,
             (!(msg_head->can_id & CAN_RTR_FLAG))))
                return -EINVAL;
 
+       /* check timeval limitations */
+       if ((msg_head->flags & SETTIMER) && bcm_is_invalid_tv(msg_head))
+               return -EINVAL;
+
        /* check the given can_id */
        op = bcm_find_op(&bo->rx_ops, msg_head, ifindex);
        if (op) {
index faa3da8..5385934 100644 (file)
@@ -416,13 +416,29 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
        while (modidx < MAX_MODFUNCTIONS && gwj->mod.modfunc[modidx])
                (*gwj->mod.modfunc[modidx++])(cf, &gwj->mod);
 
-       /* check for checksum updates when the CAN frame has been modified */
+       /* Has the CAN frame been modified? */
        if (modidx) {
-               if (gwj->mod.csumfunc.crc8)
+               /* get available space for the processed CAN frame type */
+               int max_len = nskb->len - offsetof(struct can_frame, data);
+
+               /* dlc may have changed, make sure it fits to the CAN frame */
+               if (cf->can_dlc > max_len)
+                       goto out_delete;
+
+               /* check for checksum updates in classic CAN length only */
+               if (gwj->mod.csumfunc.crc8) {
+                       if (cf->can_dlc > 8)
+                               goto out_delete;
+
                        (*gwj->mod.csumfunc.crc8)(cf, &gwj->mod.csum.crc8);
+               }
+
+               if (gwj->mod.csumfunc.xor) {
+                       if (cf->can_dlc > 8)
+                               goto out_delete;
 
-               if (gwj->mod.csumfunc.xor)
                        (*gwj->mod.csumfunc.xor)(cf, &gwj->mod.csum.xor);
+               }
        }
 
        /* clear the skb timestamp if not configured the other way */
@@ -434,6 +450,14 @@ static void can_can_gw_rcv(struct sk_buff *skb, void *data)
                gwj->dropped_frames++;
        else
                gwj->handled_frames++;
+
+       return;
+
+ out_delete:
+       /* delete frame due to misconfiguration */
+       gwj->deleted_frames++;
+       kfree_skb(nskb);
+       return;
 }
 
 static inline int cgw_register_filter(struct net *net, struct cgw_job *gwj)
index 87afb9e..9cab802 100644 (file)
@@ -255,6 +255,7 @@ enum {
        Opt_nocephx_sign_messages,
        Opt_tcp_nodelay,
        Opt_notcp_nodelay,
+       Opt_abort_on_full,
 };
 
 static match_table_t opt_tokens = {
@@ -280,6 +281,7 @@ static match_table_t opt_tokens = {
        {Opt_nocephx_sign_messages, "nocephx_sign_messages"},
        {Opt_tcp_nodelay, "tcp_nodelay"},
        {Opt_notcp_nodelay, "notcp_nodelay"},
+       {Opt_abort_on_full, "abort_on_full"},
        {-1, NULL}
 };
 
@@ -535,6 +537,10 @@ ceph_parse_options(char *options, const char *dev_name,
                        opt->flags &= ~CEPH_OPT_TCP_NODELAY;
                        break;
 
+               case Opt_abort_on_full:
+                       opt->flags |= CEPH_OPT_ABORT_ON_FULL;
+                       break;
+
                default:
                        BUG_ON(token);
                }
@@ -549,7 +555,8 @@ out:
 }
 EXPORT_SYMBOL(ceph_parse_options);
 
-int ceph_print_client_options(struct seq_file *m, struct ceph_client *client)
+int ceph_print_client_options(struct seq_file *m, struct ceph_client *client,
+                             bool show_all)
 {
        struct ceph_options *opt = client->options;
        size_t pos = m->count;
@@ -574,6 +581,8 @@ int ceph_print_client_options(struct seq_file *m, struct ceph_client *client)
                seq_puts(m, "nocephx_sign_messages,");
        if ((opt->flags & CEPH_OPT_TCP_NODELAY) == 0)
                seq_puts(m, "notcp_nodelay,");
+       if (show_all && (opt->flags & CEPH_OPT_ABORT_ON_FULL))
+               seq_puts(m, "abort_on_full,");
 
        if (opt->mount_timeout != CEPH_MOUNT_TIMEOUT_DEFAULT)
                seq_printf(m, "mount_timeout=%d,",
index 0295260..46f6570 100644 (file)
@@ -375,7 +375,7 @@ static int client_options_show(struct seq_file *s, void *p)
        struct ceph_client *client = s->private;
        int ret;
 
-       ret = ceph_print_client_options(s, client);
+       ret = ceph_print_client_options(s, client, true);
        if (ret)
                return ret;
 
index d571828..7e71b0d 100644 (file)
@@ -2058,6 +2058,8 @@ static int process_connect(struct ceph_connection *con)
        dout("process_connect on %p tag %d\n", con, (int)con->in_tag);
 
        if (con->auth) {
+               int len = le32_to_cpu(con->in_reply.authorizer_len);
+
                /*
                 * Any connection that defines ->get_authorizer()
                 * should also define ->add_authorizer_challenge() and
@@ -2067,8 +2069,7 @@ static int process_connect(struct ceph_connection *con)
                 */
                if (con->in_reply.tag == CEPH_MSGR_TAG_CHALLENGE_AUTHORIZER) {
                        ret = con->ops->add_authorizer_challenge(
-                                   con, con->auth->authorizer_reply_buf,
-                                   le32_to_cpu(con->in_reply.authorizer_len));
+                                   con, con->auth->authorizer_reply_buf, len);
                        if (ret < 0)
                                return ret;
 
@@ -2078,10 +2079,12 @@ static int process_connect(struct ceph_connection *con)
                        return 0;
                }
 
-               ret = con->ops->verify_authorizer_reply(con);
-               if (ret < 0) {
-                       con->error_msg = "bad authorize reply";
-                       return ret;
+               if (len) {
+                       ret = con->ops->verify_authorizer_reply(con);
+                       if (ret < 0) {
+                               con->error_msg = "bad authorize reply";
+                               return ret;
+                       }
                }
        }
 
@@ -3206,9 +3209,10 @@ void ceph_con_keepalive(struct ceph_connection *con)
        dout("con_keepalive %p\n", con);
        mutex_lock(&con->mutex);
        clear_standby(con);
+       con_flag_set(con, CON_FLAG_KEEPALIVE_PENDING);
        mutex_unlock(&con->mutex);
-       if (con_flag_test_and_set(con, CON_FLAG_KEEPALIVE_PENDING) == 0 &&
-           con_flag_test_and_set(con, CON_FLAG_WRITE_PENDING) == 0)
+
+       if (con_flag_test_and_set(con, CON_FLAG_WRITE_PENDING) == 0)
                queue_con(con);
 }
 EXPORT_SYMBOL(ceph_con_keepalive);
index d23a9f8..fa9530d 100644 (file)
@@ -2315,7 +2315,7 @@ again:
                   (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) ||
                    pool_full(osdc, req->r_t.base_oloc.pool))) {
                dout("req %p full/pool_full\n", req);
-               if (osdc->abort_on_full) {
+               if (ceph_test_opt(osdc->client, ABORT_ON_FULL)) {
                        err = -ENOSPC;
                } else {
                        pr_warn_ratelimited("FULL or reached pool quota\n");
@@ -2545,7 +2545,7 @@ static void ceph_osdc_abort_on_full(struct ceph_osd_client *osdc)
 {
        bool victims = false;
 
-       if (osdc->abort_on_full &&
+       if (ceph_test_opt(osdc->client, ABORT_ON_FULL) &&
            (ceph_osdmap_flag(osdc, CEPH_OSDMAP_FULL) || have_pool_full(osdc)))
                for_each_request(osdc, abort_on_full_fn, &victims);
 }
index 959d1c5..3d34819 100644 (file)
@@ -388,8 +388,12 @@ static int __compat_sys_setsockopt(int fd, int level, int optname,
                                   char __user *optval, unsigned int optlen)
 {
        int err;
-       struct socket *sock = sockfd_lookup(fd, &err);
+       struct socket *sock;
+
+       if (optlen > INT_MAX)
+               return -EINVAL;
 
+       sock = sockfd_lookup(fd, &err);
        if (sock) {
                err = security_socket_setsockopt(sock, level, optname);
                if (err) {
index 82f2002..5d03889 100644 (file)
@@ -8152,7 +8152,7 @@ static netdev_features_t netdev_sync_upper_features(struct net_device *lower,
        netdev_features_t feature;
        int feature_bit;
 
-       for_each_netdev_feature(&upper_disables, feature_bit) {
+       for_each_netdev_feature(upper_disables, feature_bit) {
                feature = __NETIF_F_BIT(feature_bit);
                if (!(upper->wanted_features & feature)
                    && (features & feature)) {
@@ -8172,7 +8172,7 @@ static void netdev_sync_lower_features(struct net_device *upper,
        netdev_features_t feature;
        int feature_bit;
 
-       for_each_netdev_feature(&upper_disables, feature_bit) {
+       for_each_netdev_feature(upper_disables, feature_bit) {
                feature = __NETIF_F_BIT(feature_bit);
                if (!(features & feature) && (lower->features & feature)) {
                        netdev_dbg(upper, "Disabling feature %pNF on lower dev %s.\n",
@@ -8712,6 +8712,9 @@ int init_dummy_netdev(struct net_device *dev)
        set_bit(__LINK_STATE_PRESENT, &dev->state);
        set_bit(__LINK_STATE_START, &dev->state);
 
+       /* napi_busy_loop stats accounting wants this */
+       dev_net_set(dev, &init_net);
+
        /* Note : We dont allocate pcpu_refcnt for dummy devices,
         * because users of this 'device' dont need to change
         * its refcount.
index 447dd1b..f7d0004 100644 (file)
@@ -2020,18 +2020,19 @@ static inline int __bpf_tx_skb(struct net_device *dev, struct sk_buff *skb)
 static int __bpf_redirect_no_mac(struct sk_buff *skb, struct net_device *dev,
                                 u32 flags)
 {
-       /* skb->mac_len is not set on normal egress */
-       unsigned int mlen = skb->network_header - skb->mac_header;
+       unsigned int mlen = skb_network_offset(skb);
 
-       __skb_pull(skb, mlen);
+       if (mlen) {
+               __skb_pull(skb, mlen);
 
-       /* At ingress, the mac header has already been pulled once.
-        * At egress, skb_pospull_rcsum has to be done in case that
-        * the skb is originated from ingress (i.e. a forwarded skb)
-        * to ensure that rcsum starts at net header.
-        */
-       if (!skb_at_tc_ingress(skb))
-               skb_postpull_rcsum(skb, skb_mac_header(skb), mlen);
+               /* At ingress, the mac header has already been pulled once.
+                * At egress, skb_pospull_rcsum has to be done in case that
+                * the skb is originated from ingress (i.e. a forwarded skb)
+                * to ensure that rcsum starts at net header.
+                */
+               if (!skb_at_tc_ingress(skb))
+                       skb_postpull_rcsum(skb, skb_mac_header(skb), mlen);
+       }
        skb_pop_mac_header(skb);
        skb_reset_mac_len(skb);
        return flags & BPF_F_INGRESS ?
@@ -2788,8 +2789,7 @@ static int bpf_skb_proto_4_to_6(struct sk_buff *skb)
        u32 off = skb_mac_header_len(skb);
        int ret;
 
-       /* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
-       if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
+       if (!skb_is_gso_tcp(skb))
                return -ENOTSUPP;
 
        ret = skb_cow(skb, len_diff);
@@ -2830,8 +2830,7 @@ static int bpf_skb_proto_6_to_4(struct sk_buff *skb)
        u32 off = skb_mac_header_len(skb);
        int ret;
 
-       /* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
-       if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
+       if (!skb_is_gso_tcp(skb))
                return -ENOTSUPP;
 
        ret = skb_unclone(skb, GFP_ATOMIC);
@@ -2956,8 +2955,7 @@ static int bpf_skb_net_grow(struct sk_buff *skb, u32 len_diff)
        u32 off = skb_mac_header_len(skb) + bpf_skb_net_base_len(skb);
        int ret;
 
-       /* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
-       if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
+       if (!skb_is_gso_tcp(skb))
                return -ENOTSUPP;
 
        ret = skb_cow(skb, len_diff);
@@ -2986,8 +2984,7 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 len_diff)
        u32 off = skb_mac_header_len(skb) + bpf_skb_net_base_len(skb);
        int ret;
 
-       /* SCTP uses GSO_BY_FRAGS, thus cannot adjust it. */
-       if (skb_is_gso(skb) && unlikely(skb_is_gso_sctp(skb)))
+       if (!skb_is_gso_tcp(skb))
                return -ENOTSUPP;
 
        ret = skb_unclone(skb, GFP_ATOMIC);
@@ -4111,14 +4108,20 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
                /* Only some socketops are supported */
                switch (optname) {
                case SO_RCVBUF:
+                       val = min_t(u32, val, sysctl_rmem_max);
                        sk->sk_userlocks |= SOCK_RCVBUF_LOCK;
                        sk->sk_rcvbuf = max_t(int, val * 2, SOCK_MIN_RCVBUF);
                        break;
                case SO_SNDBUF:
+                       val = min_t(u32, val, sysctl_wmem_max);
                        sk->sk_userlocks |= SOCK_SNDBUF_LOCK;
                        sk->sk_sndbuf = max_t(int, val * 2, SOCK_MIN_SNDBUF);
                        break;
                case SO_MAX_PACING_RATE: /* 32bit version */
+                       if (val != ~0U)
+                               cmpxchg(&sk->sk_pacing_status,
+                                       SK_PACING_NONE,
+                                       SK_PACING_NEEDED);
                        sk->sk_max_pacing_rate = (val == ~0U) ? ~0UL : val;
                        sk->sk_pacing_rate = min(sk->sk_pacing_rate,
                                                 sk->sk_max_pacing_rate);
@@ -4132,7 +4135,10 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
                        sk->sk_rcvlowat = val ? : 1;
                        break;
                case SO_MARK:
-                       sk->sk_mark = val;
+                       if (sk->sk_mark != val) {
+                               sk->sk_mark = val;
+                               sk_dst_reset(sk);
+                       }
                        break;
                default:
                        ret = -EINVAL;
@@ -4203,7 +4209,7 @@ BPF_CALL_5(bpf_setsockopt, struct bpf_sock_ops_kern *, bpf_sock,
                        /* Only some options are supported */
                        switch (optname) {
                        case TCP_BPF_IW:
-                               if (val <= 0 || tp->data_segs_out > 0)
+                               if (val <= 0 || tp->data_segs_out > tp->syn_data)
                                        ret = -EINVAL;
                                else
                                        tp->snd_cwnd = val;
@@ -5309,7 +5315,7 @@ bpf_base_func_proto(enum bpf_func_id func_id)
        case BPF_FUNC_trace_printk:
                if (capable(CAP_SYS_ADMIN))
                        return bpf_get_trace_printk_proto();
-               /* else: fall through */
+               /* else, fall through */
        default:
                return NULL;
        }
index 3e85437..a648568 100644 (file)
@@ -63,6 +63,7 @@ static int run_lwt_bpf(struct sk_buff *skb, struct bpf_lwt_prog *lwt,
                                     lwt->name ? : "<unknown>");
                        ret = BPF_OK;
                } else {
+                       skb_reset_mac_header(skb);
                        ret = skb_do_redirect(skb);
                        if (ret == 0)
                                ret = BPF_REDIRECT;
index 763a7b0..4230400 100644 (file)
@@ -18,6 +18,7 @@
 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
 
 #include <linux/slab.h>
+#include <linux/kmemleak.h>
 #include <linux/types.h>
 #include <linux/kernel.h>
 #include <linux/module.h>
@@ -443,12 +444,14 @@ static struct neigh_hash_table *neigh_hash_alloc(unsigned int shift)
        ret = kmalloc(sizeof(*ret), GFP_ATOMIC);
        if (!ret)
                return NULL;
-       if (size <= PAGE_SIZE)
+       if (size <= PAGE_SIZE) {
                buckets = kzalloc(size, GFP_ATOMIC);
-       else
+       } else {
                buckets = (struct neighbour __rcu **)
                          __get_free_pages(GFP_ATOMIC | __GFP_ZERO,
                                           get_order(size));
+               kmemleak_alloc(buckets, size, 1, GFP_ATOMIC);
+       }
        if (!buckets) {
                kfree(ret);
                return NULL;
@@ -468,10 +471,12 @@ static void neigh_hash_free_rcu(struct rcu_head *head)
        size_t size = (1 << nht->hash_shift) * sizeof(struct neighbour *);
        struct neighbour __rcu **buckets = nht->hash_buckets;
 
-       if (size <= PAGE_SIZE)
+       if (size <= PAGE_SIZE) {
                kfree(buckets);
-       else
+       } else {
+               kmemleak_free(buckets);
                free_pages((unsigned long)buckets, get_order(size));
+       }
        kfree(nht);
 }
 
@@ -1002,7 +1007,7 @@ static void neigh_probe(struct neighbour *neigh)
        if (neigh->ops->solicit)
                neigh->ops->solicit(neigh, skb);
        atomic_inc(&neigh->probes);
-       kfree_skb(skb);
+       consume_skb(skb);
 }
 
 /* Called when a timer expires for a neighbour entry. */
index 37317ff..2415d9c 100644 (file)
@@ -356,6 +356,8 @@ static void *__netdev_alloc_frag(unsigned int fragsz, gfp_t gfp_mask)
  */
 void *netdev_alloc_frag(unsigned int fragsz)
 {
+       fragsz = SKB_DATA_ALIGN(fragsz);
+
        return __netdev_alloc_frag(fragsz, GFP_ATOMIC);
 }
 EXPORT_SYMBOL(netdev_alloc_frag);
@@ -369,6 +371,8 @@ static void *__napi_alloc_frag(unsigned int fragsz, gfp_t gfp_mask)
 
 void *napi_alloc_frag(unsigned int fragsz)
 {
+       fragsz = SKB_DATA_ALIGN(fragsz);
+
        return __napi_alloc_frag(fragsz, GFP_ATOMIC);
 }
 EXPORT_SYMBOL(napi_alloc_frag);
@@ -5270,7 +5274,6 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len,
        unsigned long chunk;
        struct sk_buff *skb;
        struct page *page;
-       gfp_t gfp_head;
        int i;
 
        *errcode = -EMSGSIZE;
@@ -5280,12 +5283,8 @@ struct sk_buff *alloc_skb_with_frags(unsigned long header_len,
        if (npages > MAX_SKB_FRAGS)
                return NULL;
 
-       gfp_head = gfp_mask;
-       if (gfp_head & __GFP_DIRECT_RECLAIM)
-               gfp_head |= __GFP_RETRY_MAYFAIL;
-
        *errcode = -ENOBUFS;
-       skb = alloc_skb(header_len, gfp_head);
+       skb = alloc_skb(header_len, gfp_mask);
        if (!skb)
                return NULL;
 
index d6d5c20..8c82660 100644 (file)
@@ -545,8 +545,7 @@ static void sk_psock_destroy_deferred(struct work_struct *gc)
        struct sk_psock *psock = container_of(gc, struct sk_psock, gc);
 
        /* No sk_callback_lock since already detached. */
-       if (psock->parser.enabled)
-               strp_done(&psock->parser.strp);
+       strp_done(&psock->parser.strp);
 
        cancel_work_sync(&psock->work);
 
index 6aa2e7e..bc3512f 100644 (file)
@@ -2380,7 +2380,7 @@ int __sk_mem_raise_allocated(struct sock *sk, int size, int amt, int kind)
        }
 
        if (sk_has_memory_pressure(sk)) {
-               int alloc;
+               u64 alloc;
 
                if (!sk_under_memory_pressure(sk))
                        return 1;
index 6eb837a..baaaeb2 100644 (file)
@@ -202,7 +202,7 @@ static inline void ccid_hc_tx_packet_recv(struct ccid *ccid, struct sock *sk,
 static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
                                           u8 pkt, u8 opt, u8 *val, u8 len)
 {
-       if (ccid->ccid_ops->ccid_hc_tx_parse_options == NULL)
+       if (!ccid || !ccid->ccid_ops->ccid_hc_tx_parse_options)
                return 0;
        return ccid->ccid_ops->ccid_hc_tx_parse_options(sk, pkt, opt, val, len);
 }
@@ -214,7 +214,7 @@ static inline int ccid_hc_tx_parse_options(struct ccid *ccid, struct sock *sk,
 static inline int ccid_hc_rx_parse_options(struct ccid *ccid, struct sock *sk,
                                           u8 pkt, u8 opt, u8 *val, u8 len)
 {
-       if (ccid->ccid_ops->ccid_hc_rx_parse_options == NULL)
+       if (!ccid || !ccid->ccid_ops->ccid_hc_rx_parse_options)
                return 0;
        return ccid->ccid_ops->ccid_hc_rx_parse_options(sk, pkt, opt, val, len);
 }
index d0b3e69..0962f92 100644 (file)
@@ -56,7 +56,7 @@
 #include <net/dn_neigh.h>
 #include <net/dn_fib.h>
 
-#define DN_IFREQ_SIZE (sizeof(struct ifreq) - sizeof(struct sockaddr) + sizeof(struct sockaddr_dn))
+#define DN_IFREQ_SIZE (offsetof(struct ifreq, ifr_ifru) + sizeof(struct sockaddr_dn))
 
 static char dn_rt_all_end_mcast[ETH_ALEN] = {0xAB,0x00,0x00,0x04,0x00,0x00};
 static char dn_rt_all_rt_mcast[ETH_ALEN]  = {0xAB,0x00,0x00,0x03,0x00,0x00};
index 71bb15f..54f5551 100644 (file)
@@ -205,6 +205,8 @@ static void dsa_master_reset_mtu(struct net_device *dev)
        rtnl_unlock();
 }
 
+static struct lock_class_key dsa_master_addr_list_lock_key;
+
 int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
 {
        int ret;
@@ -218,6 +220,8 @@ int dsa_master_setup(struct net_device *dev, struct dsa_port *cpu_dp)
        wmb();
 
        dev->dsa_ptr = cpu_dp;
+       lockdep_set_class(&dev->addr_list_lock,
+                         &dsa_master_addr_list_lock_key);
 
        ret = dsa_master_ethtool_setup(dev);
        if (ret)
index 2d7e01b..2a2a878 100644 (file)
@@ -69,7 +69,6 @@ static void dsa_port_set_state_now(struct dsa_port *dp, u8 state)
 
 int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy)
 {
-       u8 stp_state = dp->bridge_dev ? BR_STATE_BLOCKING : BR_STATE_FORWARDING;
        struct dsa_switch *ds = dp->ds;
        int port = dp->index;
        int err;
@@ -80,7 +79,8 @@ int dsa_port_enable(struct dsa_port *dp, struct phy_device *phy)
                        return err;
        }
 
-       dsa_port_set_state_now(dp, stp_state);
+       if (!dp->bridge_dev)
+               dsa_port_set_state_now(dp, BR_STATE_FORWARDING);
 
        return 0;
 }
@@ -90,7 +90,8 @@ void dsa_port_disable(struct dsa_port *dp, struct phy_device *phy)
        struct dsa_switch *ds = dp->ds;
        int port = dp->index;
 
-       dsa_port_set_state_now(dp, BR_STATE_DISABLED);
+       if (!dp->bridge_dev)
+               dsa_port_set_state_now(dp, BR_STATE_DISABLED);
 
        if (ds->ops->port_disable)
                ds->ops->port_disable(ds, port, phy);
index a3fcc1d..a1c9fe1 100644 (file)
@@ -140,11 +140,14 @@ static int dsa_slave_close(struct net_device *dev)
 static void dsa_slave_change_rx_flags(struct net_device *dev, int change)
 {
        struct net_device *master = dsa_slave_to_master(dev);
-
-       if (change & IFF_ALLMULTI)
-               dev_set_allmulti(master, dev->flags & IFF_ALLMULTI ? 1 : -1);
-       if (change & IFF_PROMISC)
-               dev_set_promiscuity(master, dev->flags & IFF_PROMISC ? 1 : -1);
+       if (dev->flags & IFF_UP) {
+               if (change & IFF_ALLMULTI)
+                       dev_set_allmulti(master,
+                                        dev->flags & IFF_ALLMULTI ? 1 : -1);
+               if (change & IFF_PROMISC)
+                       dev_set_promiscuity(master,
+                                           dev->flags & IFF_PROMISC ? 1 : -1);
+       }
 }
 
 static void dsa_slave_set_rx_mode(struct net_device *dev)
@@ -639,7 +642,7 @@ static int dsa_slave_set_eee(struct net_device *dev, struct ethtool_eee *e)
        int ret;
 
        /* Port's PHY and MAC both need to be EEE capable */
-       if (!dev->phydev && !dp->pl)
+       if (!dev->phydev || !dp->pl)
                return -ENODEV;
 
        if (!ds->ops->set_mac_eee)
@@ -659,7 +662,7 @@ static int dsa_slave_get_eee(struct net_device *dev, struct ethtool_eee *e)
        int ret;
 
        /* Port's PHY and MAC both need to be EEE capable */
-       if (!dev->phydev && !dp->pl)
+       if (!dev->phydev || !dp->pl)
                return -ENODEV;
 
        if (!ds->ops->get_mac_eee)
index 5e04ed2..1e976bb 100644 (file)
@@ -1,28 +1,54 @@
 // SPDX-License-Identifier: GPL-2.0
+#include <linux/init.h>
+#include <linux/module.h>
 #include <linux/uaccess.h>
 #include <linux/bpfilter.h>
 #include <uapi/linux/bpf.h>
 #include <linux/wait.h>
 #include <linux/kmod.h>
+#include <linux/fs.h>
+#include <linux/file.h>
 
-int (*bpfilter_process_sockopt)(struct sock *sk, int optname,
-                               char __user *optval,
-                               unsigned int optlen, bool is_set);
-EXPORT_SYMBOL_GPL(bpfilter_process_sockopt);
+struct bpfilter_umh_ops bpfilter_ops;
+EXPORT_SYMBOL_GPL(bpfilter_ops);
+
+static void bpfilter_umh_cleanup(struct umh_info *info)
+{
+       mutex_lock(&bpfilter_ops.lock);
+       bpfilter_ops.stop = true;
+       fput(info->pipe_to_umh);
+       fput(info->pipe_from_umh);
+       info->pid = 0;
+       mutex_unlock(&bpfilter_ops.lock);
+}
 
 static int bpfilter_mbox_request(struct sock *sk, int optname,
                                 char __user *optval,
                                 unsigned int optlen, bool is_set)
 {
-       if (!bpfilter_process_sockopt) {
-               int err = request_module("bpfilter");
+       int err;
+       mutex_lock(&bpfilter_ops.lock);
+       if (!bpfilter_ops.sockopt) {
+               mutex_unlock(&bpfilter_ops.lock);
+               err = request_module("bpfilter");
+               mutex_lock(&bpfilter_ops.lock);
 
                if (err)
-                       return err;
-               if (!bpfilter_process_sockopt)
-                       return -ECHILD;
+                       goto out;
+               if (!bpfilter_ops.sockopt) {
+                       err = -ECHILD;
+                       goto out;
+               }
+       }
+       if (bpfilter_ops.stop) {
+               err = bpfilter_ops.start();
+               if (err)
+                       goto out;
        }
-       return bpfilter_process_sockopt(sk, optname, optval, optlen, is_set);
+       err = bpfilter_ops.sockopt(sk, optname, optval, optlen, is_set);
+out:
+       mutex_unlock(&bpfilter_ops.lock);
+       return err;
 }
 
 int bpfilter_ip_set_sockopt(struct sock *sk, int optname, char __user *optval,
@@ -41,3 +67,15 @@ int bpfilter_ip_get_sockopt(struct sock *sk, int optname, char __user *optval,
 
        return bpfilter_mbox_request(sk, optname, optval, len, false);
 }
+
+static int __init bpfilter_sockopt_init(void)
+{
+       mutex_init(&bpfilter_ops.lock);
+       bpfilter_ops.stop = true;
+       bpfilter_ops.info.cmdline = "bpfilter_umh";
+       bpfilter_ops.info.cleanup = &bpfilter_umh_cleanup;
+
+       return 0;
+}
+
+module_init(bpfilter_sockopt_init);
index 04ba321..e258a00 100644 (file)
@@ -1826,7 +1826,7 @@ put_tgt_net:
        if (fillargs.netnsid >= 0)
                put_net(tgt_net);
 
-       return err < 0 ? err : skb->len;
+       return skb->len ? : err;
 }
 
 static void rtmsg_ifa(int event, struct in_ifaddr *ifa, struct nlmsghdr *nlh,
index 5459f41..10e809b 100644 (file)
@@ -328,7 +328,7 @@ int esp_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info *
                        skb->len += tailen;
                        skb->data_len += tailen;
                        skb->truesize += tailen;
-                       if (sk)
+                       if (sk && sk_fullsock(sk))
                                refcount_add(tailen, &sk->sk_wmem_alloc);
 
                        goto out;
index 6df95be..fe4f6a6 100644 (file)
@@ -203,7 +203,7 @@ static void fib_flush(struct net *net)
                struct fib_table *tb;
 
                hlist_for_each_entry_safe(tb, tmp, head, tb_hlist)
-                       flushed += fib_table_flush(net, tb);
+                       flushed += fib_table_flush(net, tb, false);
        }
 
        if (flushed)
@@ -1463,7 +1463,7 @@ static void ip_fib_net_exit(struct net *net)
 
                hlist_for_each_entry_safe(tb, tmp, head, tb_hlist) {
                        hlist_del(&tb->tb_hlist);
-                       fib_table_flush(net, tb);
+                       fib_table_flush(net, tb, true);
                        fib_free_table(tb);
                }
        }
index 237c9f7..a573e37 100644 (file)
@@ -1856,7 +1856,7 @@ void fib_table_flush_external(struct fib_table *tb)
 }
 
 /* Caller must hold RTNL. */
-int fib_table_flush(struct net *net, struct fib_table *tb)
+int fib_table_flush(struct net *net, struct fib_table *tb, bool flush_all)
 {
        struct trie *t = (struct trie *)tb->tb_data;
        struct key_vector *pn = t->kv;
@@ -1904,8 +1904,17 @@ int fib_table_flush(struct net *net, struct fib_table *tb)
                hlist_for_each_entry_safe(fa, tmp, &n->leaf, fa_list) {
                        struct fib_info *fi = fa->fa_info;
 
-                       if (!fi || !(fi->fib_flags & RTNH_F_DEAD) ||
-                           tb->tb_id != fa->tb_id) {
+                       if (!fi || tb->tb_id != fa->tb_id ||
+                           (!(fi->fib_flags & RTNH_F_DEAD) &&
+                            !fib_props[fa->fa_type].error)) {
+                               slen = fa->fa_slen;
+                               continue;
+                       }
+
+                       /* Do not flush error routes if network namespace is
+                        * not being dismantled
+                        */
+                       if (!flush_all && fib_props[fa->fa_type].error) {
                                slen = fa->fa_slen;
                                continue;
                        }
index 0c9f171..437070d 100644 (file)
@@ -1020,10 +1020,11 @@ static int gue_err(struct sk_buff *skb, u32 info)
 {
        int transport_offset = skb_transport_offset(skb);
        struct guehdr *guehdr;
-       size_t optlen;
+       size_t len, optlen;
        int ret;
 
-       if (skb->len < sizeof(struct udphdr) + sizeof(struct guehdr))
+       len = sizeof(struct udphdr) + sizeof(struct guehdr);
+       if (!pskb_may_pull(skb, len))
                return -EINVAL;
 
        guehdr = (struct guehdr *)&udp_hdr(skb)[1];
@@ -1058,6 +1059,10 @@ static int gue_err(struct sk_buff *skb, u32 info)
 
        optlen = guehdr->hlen << 2;
 
+       if (!pskb_may_pull(skb, len + optlen))
+               return -EINVAL;
+
+       guehdr = (struct guehdr *)&udp_hdr(skb)[1];
        if (validate_gue_flags(guehdr, optlen))
                return -EINVAL;
 
@@ -1065,7 +1070,8 @@ static int gue_err(struct sk_buff *skb, u32 info)
         * recursion. Besides, this kind of encapsulation can't even be
         * configured currently. Discard this.
         */
-       if (guehdr->proto_ctype == IPPROTO_UDP)
+       if (guehdr->proto_ctype == IPPROTO_UDP ||
+           guehdr->proto_ctype == IPPROTO_UDPLITE)
                return -EOPNOTSUPP;
 
        skb_set_transport_header(skb, -(int)sizeof(struct icmphdr));
index a4bf22e..7c4a41d 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/spinlock.h>
 #include <net/protocol.h>
 #include <net/gre.h>
+#include <net/erspan.h>
 
 #include <net/icmp.h>
 #include <net/route.h>
@@ -119,6 +120,22 @@ int gre_parse_header(struct sk_buff *skb, struct tnl_ptk_info *tpi,
                        hdr_len += 4;
        }
        tpi->hdr_len = hdr_len;
+
+       /* ERSPAN ver 1 and 2 protocol sets GRE key field
+        * to 0 and sets the configured key in the
+        * inner erspan header field
+        */
+       if (greh->protocol == htons(ETH_P_ERSPAN) ||
+           greh->protocol == htons(ETH_P_ERSPAN2)) {
+               struct erspan_base_hdr *ershdr;
+
+               if (!pskb_may_pull(skb, nhs + hdr_len + sizeof(*ershdr)))
+                       return -EINVAL;
+
+               ershdr = (struct erspan_base_hdr *)options;
+               tpi->key = cpu_to_be32(get_session_id(ershdr));
+       }
+
        return hdr_len;
 }
 EXPORT_SYMBOL(gre_parse_header);
index 1a4e9ff..5731670 100644 (file)
@@ -108,6 +108,7 @@ static size_t inet_sk_attr_size(struct sock *sk,
                + nla_total_size(1) /* INET_DIAG_TOS */
                + nla_total_size(1) /* INET_DIAG_TCLASS */
                + nla_total_size(4) /* INET_DIAG_MARK */
+               + nla_total_size(4) /* INET_DIAG_CLASS_ID */
                + nla_total_size(sizeof(struct inet_diag_meminfo))
                + nla_total_size(sizeof(struct inet_diag_msg))
                + nla_total_size(SK_MEMINFO_VARS * sizeof(u32))
@@ -287,12 +288,19 @@ int inet_sk_diag_fill(struct sock *sk, struct inet_connection_sock *icsk,
                        goto errout;
        }
 
-       if (ext & (1 << (INET_DIAG_CLASS_ID - 1))) {
+       if (ext & (1 << (INET_DIAG_CLASS_ID - 1)) ||
+           ext & (1 << (INET_DIAG_TCLASS - 1))) {
                u32 classid = 0;
 
 #ifdef CONFIG_SOCK_CGROUP_DATA
                classid = sock_cgroup_classid(&sk->sk_cgrp_data);
 #endif
+               /* Fallback to socket priority if class id isn't set.
+                * Classful qdiscs use it as direct reference to class.
+                * For cgroup2 classid is always zero.
+                */
+               if (!classid)
+                       classid = sk->sk_priority;
 
                if (nla_put_u32(skb, INET_DIAG_CLASS_ID, classid))
                        goto errout;
index d757b96..be77859 100644 (file)
@@ -216,6 +216,7 @@ struct inet_peer *inet_getpeer(struct inet_peer_base *base,
                        atomic_set(&p->rid, 0);
                        p->metrics[RTAX_LOCK-1] = INETPEER_METRICS_NEW;
                        p->rate_tokens = 0;
+                       p->n_redirects = 0;
                        /* 60*HZ is arbitrary, but chosen enough high so that the first
                         * calculation of tokens is at its maximum.
                         */
index d1d09f3..6ae89f2 100644 (file)
@@ -268,20 +268,11 @@ static int erspan_rcv(struct sk_buff *skb, struct tnl_ptk_info *tpi,
        int len;
 
        itn = net_generic(net, erspan_net_id);
-       len = gre_hdr_len + sizeof(*ershdr);
-
-       /* Check based hdr len */
-       if (unlikely(!pskb_may_pull(skb, len)))
-               return PACKET_REJECT;
 
        iph = ip_hdr(skb);
        ershdr = (struct erspan_base_hdr *)(skb->data + gre_hdr_len);
        ver = ershdr->ver;
 
-       /* The original GRE header does not have key field,
-        * Use ERSPAN 10-bit session ID as key.
-        */
-       tpi->key = cpu_to_be32(get_session_id(ershdr));
        tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex,
                                  tpi->flags | TUNNEL_KEY,
                                  iph->saddr, iph->daddr, tpi->key);
@@ -569,8 +560,7 @@ err_free_skb:
        dev->stats.tx_dropped++;
 }
 
-static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
-                          __be16 proto)
+static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev)
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
        struct ip_tunnel_info *tun_info;
@@ -578,10 +568,10 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
        struct erspan_metadata *md;
        struct rtable *rt = NULL;
        bool truncate = false;
+       __be16 df, proto;
        struct flowi4 fl;
        int tunnel_hlen;
        int version;
-       __be16 df;
        int nhoff;
        int thoff;
 
@@ -626,18 +616,20 @@ static void erspan_fb_xmit(struct sk_buff *skb, struct net_device *dev,
        if (version == 1) {
                erspan_build_header(skb, ntohl(tunnel_id_to_key32(key->tun_id)),
                                    ntohl(md->u.index), truncate, true);
+               proto = htons(ETH_P_ERSPAN);
        } else if (version == 2) {
                erspan_build_header_v2(skb,
                                       ntohl(tunnel_id_to_key32(key->tun_id)),
                                       md->u.md2.dir,
                                       get_hwid(&md->u.md2),
                                       truncate, true);
+               proto = htons(ETH_P_ERSPAN2);
        } else {
                goto err_free_rt;
        }
 
        gre_build_header(skb, 8, TUNNEL_SEQ,
-                        htons(ETH_P_ERSPAN), 0, htonl(tunnel->o_seqno++));
+                        proto, 0, htonl(tunnel->o_seqno++));
 
        df = key->tun_flags & TUNNEL_DONT_FRAGMENT ?  htons(IP_DF) : 0;
 
@@ -721,12 +713,13 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
 {
        struct ip_tunnel *tunnel = netdev_priv(dev);
        bool truncate = false;
+       __be16 proto;
 
        if (!pskb_inet_may_pull(skb))
                goto free_skb;
 
        if (tunnel->collect_md) {
-               erspan_fb_xmit(skb, dev, skb->protocol);
+               erspan_fb_xmit(skb, dev);
                return NETDEV_TX_OK;
        }
 
@@ -742,19 +735,22 @@ static netdev_tx_t erspan_xmit(struct sk_buff *skb,
        }
 
        /* Push ERSPAN header */
-       if (tunnel->erspan_ver == 1)
+       if (tunnel->erspan_ver == 1) {
                erspan_build_header(skb, ntohl(tunnel->parms.o_key),
                                    tunnel->index,
                                    truncate, true);
-       else if (tunnel->erspan_ver == 2)
+               proto = htons(ETH_P_ERSPAN);
+       } else if (tunnel->erspan_ver == 2) {
                erspan_build_header_v2(skb, ntohl(tunnel->parms.o_key),
                                       tunnel->dir, tunnel->hwid,
                                       truncate, true);
-       else
+               proto = htons(ETH_P_ERSPAN2);
+       } else {
                goto free_skb;
+       }
 
        tunnel->parms.o_flags &= ~TUNNEL_KEY;
-       __gre_xmit(skb, dev, &tunnel->parms.iph, htons(ETH_P_ERSPAN));
+       __gre_xmit(skb, dev, &tunnel->parms.iph, proto);
        return NETDEV_TX_OK;
 
 free_skb:
@@ -1459,12 +1455,31 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
        struct ip_tunnel *t = netdev_priv(dev);
        struct ip_tunnel_parm *p = &t->parms;
+       __be16 o_flags = p->o_flags;
+
+       if (t->erspan_ver == 1 || t->erspan_ver == 2) {
+               if (!t->collect_md)
+                       o_flags |= TUNNEL_KEY;
+
+               if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver))
+                       goto nla_put_failure;
+
+               if (t->erspan_ver == 1) {
+                       if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index))
+                               goto nla_put_failure;
+               } else {
+                       if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, t->dir))
+                               goto nla_put_failure;
+                       if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, t->hwid))
+                               goto nla_put_failure;
+               }
+       }
 
        if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
            nla_put_be16(skb, IFLA_GRE_IFLAGS,
                         gre_tnl_flags_to_gre_flags(p->i_flags)) ||
            nla_put_be16(skb, IFLA_GRE_OFLAGS,
-                        gre_tnl_flags_to_gre_flags(p->o_flags)) ||
+                        gre_tnl_flags_to_gre_flags(o_flags)) ||
            nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
            nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
            nla_put_in_addr(skb, IFLA_GRE_LOCAL, p->iph.saddr) ||
@@ -1494,19 +1509,6 @@ static int ipgre_fill_info(struct sk_buff *skb, const struct net_device *dev)
                        goto nla_put_failure;
        }
 
-       if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, t->erspan_ver))
-               goto nla_put_failure;
-
-       if (t->erspan_ver == 1) {
-               if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, t->index))
-                       goto nla_put_failure;
-       } else if (t->erspan_ver == 2) {
-               if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, t->dir))
-                       goto nla_put_failure;
-               if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, t->hwid))
-                       goto nla_put_failure;
-       }
-
        return 0;
 
 nla_put_failure:
index 26921f6..51d8efb 100644 (file)
@@ -488,6 +488,7 @@ static struct sk_buff *ip_rcv_core(struct sk_buff *skb, struct net *net)
                goto drop;
        }
 
+       iph = ip_hdr(skb);
        skb->transport_header = skb->network_header + iph->ihl*4;
 
        /* Remove any debris in the socket control block */
index fffcc13..82f341e 100644 (file)
@@ -148,19 +148,17 @@ static void ip_cmsg_recv_security(struct msghdr *msg, struct sk_buff *skb)
 
 static void ip_cmsg_recv_dstaddr(struct msghdr *msg, struct sk_buff *skb)
 {
+       __be16 _ports[2], *ports;
        struct sockaddr_in sin;
-       __be16 *ports;
-       int end;
-
-       end = skb_transport_offset(skb) + 4;
-       if (end > 0 && !pskb_may_pull(skb, end))
-               return;
 
        /* All current transport protocols have the port numbers in the
         * first four bytes of the transport header and this function is
         * written with this assumption in mind.
         */
-       ports = (__be16 *)skb_transport_header(skb);
+       ports = skb_header_pointer(skb, skb_transport_offset(skb),
+                                  sizeof(_ports), &_ports);
+       if (!ports)
+               return;
 
        sin.sin_family = AF_INET;
        sin.sin_addr.s_addr = ip_hdr(skb)->daddr;
index c4f5602..054d01c 100644 (file)
@@ -644,13 +644,19 @@ void ip_tunnel_xmit(struct sk_buff *skb, struct net_device *dev,
        dst = tnl_params->daddr;
        if (dst == 0) {
                /* NBMA tunnel */
+               struct ip_tunnel_info *tun_info;
 
                if (!skb_dst(skb)) {
                        dev->stats.tx_fifo_errors++;
                        goto tx_error;
                }
 
-               if (skb->protocol == htons(ETH_P_IP)) {
+               tun_info = skb_tunnel_info(skb);
+               if (tun_info && (tun_info->mode & IP_TUNNEL_INFO_TX) &&
+                   ip_tunnel_info_af(tun_info) == AF_INET &&
+                   tun_info->key.u.ipv4.dst)
+                       dst = tun_info->key.u.ipv4.dst;
+               else if (skb->protocol == htons(ETH_P_IP)) {
                        rt = skb_rtable(skb);
                        dst = rt_nexthop(rt, inner_iph->daddr);
                }
index d7b43e7..68a21bf 100644 (file)
@@ -74,6 +74,33 @@ drop:
        return 0;
 }
 
+static int vti_input_ipip(struct sk_buff *skb, int nexthdr, __be32 spi,
+                    int encap_type)
+{
+       struct ip_tunnel *tunnel;
+       const struct iphdr *iph = ip_hdr(skb);
+       struct net *net = dev_net(skb->dev);
+       struct ip_tunnel_net *itn = net_generic(net, vti_net_id);
+
+       tunnel = ip_tunnel_lookup(itn, skb->dev->ifindex, TUNNEL_NO_KEY,
+                                 iph->saddr, iph->daddr, 0);
+       if (tunnel) {
+               if (!xfrm4_policy_check(NULL, XFRM_POLICY_IN, skb))
+                       goto drop;
+
+               XFRM_TUNNEL_SKB_CB(skb)->tunnel.ip4 = tunnel;
+
+               skb->dev = tunnel->dev;
+
+               return xfrm_input(skb, nexthdr, spi, encap_type);
+       }
+
+       return -EINVAL;
+drop:
+       kfree_skb(skb);
+       return 0;
+}
+
 static int vti_rcv(struct sk_buff *skb)
 {
        XFRM_SPI_SKB_CB(skb)->family = AF_INET;
@@ -82,6 +109,14 @@ static int vti_rcv(struct sk_buff *skb)
        return vti_input(skb, ip_hdr(skb)->protocol, 0, 0);
 }
 
+static int vti_rcv_ipip(struct sk_buff *skb)
+{
+       XFRM_SPI_SKB_CB(skb)->family = AF_INET;
+       XFRM_SPI_SKB_CB(skb)->daddroff = offsetof(struct iphdr, daddr);
+
+       return vti_input_ipip(skb, ip_hdr(skb)->protocol, ip_hdr(skb)->saddr, 0);
+}
+
 static int vti_rcv_cb(struct sk_buff *skb, int err)
 {
        unsigned short family;
@@ -435,6 +470,12 @@ static struct xfrm4_protocol vti_ipcomp4_protocol __read_mostly = {
        .priority       =       100,
 };
 
+static struct xfrm_tunnel ipip_handler __read_mostly = {
+       .handler        =       vti_rcv_ipip,
+       .err_handler    =       vti4_err,
+       .priority       =       0,
+};
+
 static int __net_init vti_init_net(struct net *net)
 {
        int err;
@@ -603,6 +644,13 @@ static int __init vti_init(void)
        if (err < 0)
                goto xfrm_proto_comp_failed;
 
+       msg = "ipip tunnel";
+       err = xfrm4_tunnel_register(&ipip_handler, AF_INET);
+       if (err < 0) {
+               pr_info("%s: cant't register tunnel\n",__func__);
+               goto xfrm_tunnel_failed;
+       }
+
        msg = "netlink interface";
        err = rtnl_link_register(&vti_link_ops);
        if (err < 0)
@@ -612,6 +660,8 @@ static int __init vti_init(void)
 
 rtnl_link_failed:
        xfrm4_protocol_deregister(&vti_ipcomp4_protocol, IPPROTO_COMP);
+xfrm_tunnel_failed:
+       xfrm4_tunnel_deregister(&ipip_handler, AF_INET);
 xfrm_proto_comp_failed:
        xfrm4_protocol_deregister(&vti_ah4_protocol, IPPROTO_AH);
 xfrm_proto_ah_failed:
index b61977d..2a909e5 100644 (file)
@@ -846,9 +846,9 @@ static int clusterip_net_init(struct net *net)
 
 static void clusterip_net_exit(struct net *net)
 {
+#ifdef CONFIG_PROC_FS
        struct clusterip_net *cn = clusterip_pernet(net);
 
-#ifdef CONFIG_PROC_FS
        mutex_lock(&cn->mutex);
        proc_remove(cn->procdir);
        cn->procdir = NULL;
index 2687db0..fa2ba7c 100644 (file)
@@ -215,6 +215,7 @@ int nf_nat_icmp_reply_translation(struct sk_buff *skb,
 
        /* Change outer to look like the reply to an incoming packet */
        nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
+       target.dst.protonum = IPPROTO_ICMP;
        if (!nf_nat_ipv4_manip_pkt(skb, 0, &target, manip))
                return 0;
 
index a0aa13b..0a8a60c 100644 (file)
@@ -105,6 +105,8 @@ static void fast_csum(struct snmp_ctx *ctx, unsigned char offset)
 int snmp_version(void *context, size_t hdrlen, unsigned char tag,
                 const void *data, size_t datalen)
 {
+       if (datalen != 1)
+               return -EINVAL;
        if (*(unsigned char *)data > 1)
                return -ENOTSUPP;
        return 1;
@@ -114,8 +116,11 @@ int snmp_helper(void *context, size_t hdrlen, unsigned char tag,
                const void *data, size_t datalen)
 {
        struct snmp_ctx *ctx = (struct snmp_ctx *)context;
-       __be32 *pdata = (__be32 *)data;
+       __be32 *pdata;
 
+       if (datalen != 4)
+               return -EINVAL;
+       pdata = (__be32 *)data;
        if (*pdata == ctx->from) {
                pr_debug("%s: %pI4 to %pI4\n", __func__,
                         (void *)&ctx->from, (void *)&ctx->to);
index ce92f73..5163b64 100644 (file)
@@ -887,13 +887,15 @@ void ip_rt_send_redirect(struct sk_buff *skb)
        /* No redirected packets during ip_rt_redirect_silence;
         * reset the algorithm.
         */
-       if (time_after(jiffies, peer->rate_last + ip_rt_redirect_silence))
+       if (time_after(jiffies, peer->rate_last + ip_rt_redirect_silence)) {
                peer->rate_tokens = 0;
+               peer->n_redirects = 0;
+       }
 
        /* Too many ignored redirects; do not send anything
         * set dst.rate_last to the last seen redirected packet.
         */
-       if (peer->rate_tokens >= ip_rt_redirect_number) {
+       if (peer->n_redirects >= ip_rt_redirect_number) {
                peer->rate_last = jiffies;
                goto out_put_peer;
        }
@@ -910,6 +912,7 @@ void ip_rt_send_redirect(struct sk_buff *skb)
                icmp_send(skb, ICMP_REDIRECT, ICMP_REDIR_HOST, gw);
                peer->rate_last = jiffies;
                ++peer->rate_tokens;
+               ++peer->n_redirects;
 #ifdef CONFIG_IP_ROUTE_VERBOSE
                if (log_martians &&
                    peer->rate_tokens == ip_rt_redirect_number)
index 27e2f68..cf3c509 100644 (file)
@@ -1186,7 +1186,7 @@ int tcp_sendmsg_locked(struct sock *sk, struct msghdr *msg, size_t size)
        flags = msg->msg_flags;
 
        if (flags & MSG_ZEROCOPY && size && sock_flag(sk, SOCK_ZEROCOPY)) {
-               if (sk->sk_state != TCP_ESTABLISHED) {
+               if ((1 << sk->sk_state) & ~(TCPF_ESTABLISHED | TCPF_CLOSE_WAIT)) {
                        err = -EINVAL;
                        goto out_err;
                }
@@ -2528,6 +2528,7 @@ void tcp_write_queue_purge(struct sock *sk)
        sk_mem_reclaim(sk);
        tcp_clear_all_retrans_hints(tcp_sk(sk));
        tcp_sk(sk)->packets_out = 0;
+       inet_csk(sk)->icsk_backoff = 0;
 }
 
 int tcp_disconnect(struct sock *sk, int flags)
@@ -2576,7 +2577,6 @@ int tcp_disconnect(struct sock *sk, int flags)
        tp->write_seq += tp->max_window + 2;
        if (tp->write_seq == 0)
                tp->write_seq = 1;
-       icsk->icsk_backoff = 0;
        tp->snd_cwnd = 2;
        icsk->icsk_probes_out = 0;
        tp->snd_ssthresh = TCP_INFINITE_SSTHRESH;
index efc6fef..ec3cea9 100644 (file)
@@ -536,12 +536,15 @@ int tcp_v4_err(struct sk_buff *icmp_skb, u32 info)
                if (sock_owned_by_user(sk))
                        break;
 
+               skb = tcp_rtx_queue_head(sk);
+               if (WARN_ON_ONCE(!skb))
+                       break;
+
                icsk->icsk_backoff--;
                icsk->icsk_rto = tp->srtt_us ? __tcp_set_rto(tp) :
                                               TCP_TIMEOUT_INIT;
                icsk->icsk_rto = inet_csk_rto_backoff(icsk, TCP_RTO_MAX);
 
-               skb = tcp_rtx_queue_head(sk);
 
                tcp_mstamp_refresh(tp);
                delta_us = (u32)(tp->tcp_mstamp - tcp_skb_timestamp_us(skb));
index 730bc44..ccc78f3 100644 (file)
@@ -2347,6 +2347,7 @@ static bool tcp_write_xmit(struct sock *sk, unsigned int mss_now, int nonagle,
                        /* "skb_mstamp_ns" is used as a start point for the retransmit timer */
                        skb->skb_mstamp_ns = tp->tcp_wstamp_ns = tp->tcp_clock_cache;
                        list_move_tail(&skb->tcp_tsorted_anchor, &tp->tsorted_sent_queue);
+                       tcp_init_tso_segs(skb, mss_now);
                        goto repair; /* Skip network transmission */
                }
 
index f87dbc7..71a29e9 100644 (file)
@@ -226,7 +226,7 @@ static int tcp_write_timeout(struct sock *sk)
        if ((1 << sk->sk_state) & (TCPF_SYN_SENT | TCPF_SYN_RECV)) {
                if (icsk->icsk_retransmits) {
                        dst_negative_advice(sk);
-               } else if (!tp->syn_data && !tp->syn_fastopen) {
+               } else {
                        sk_rethink_txhash(sk);
                }
                retry_until = icsk->icsk_syn_retries ? : net->ipv4.sysctl_tcp_syn_retries;
index 3fb0ed5..372fdc5 100644 (file)
@@ -562,10 +562,12 @@ static int __udp4_lib_err_encap_no_sk(struct sk_buff *skb, u32 info)
 
        for (i = 0; i < MAX_IPTUN_ENCAP_OPS; i++) {
                int (*handler)(struct sk_buff *skb, u32 info);
+               const struct ip_tunnel_encap_ops *encap;
 
-               if (!iptun_encaps[i])
+               encap = rcu_dereference(iptun_encaps[i]);
+               if (!encap)
                        continue;
-               handler = rcu_dereference(iptun_encaps[i]->err_handler);
+               handler = encap->err_handler;
                if (handler && !handler(skb, info))
                        return 0;
        }
@@ -847,15 +849,23 @@ static int udp_send_skb(struct sk_buff *skb, struct flowi4 *fl4,
                const int hlen = skb_network_header_len(skb) +
                                 sizeof(struct udphdr);
 
-               if (hlen + cork->gso_size > cork->fragsize)
+               if (hlen + cork->gso_size > cork->fragsize) {
+                       kfree_skb(skb);
                        return -EINVAL;
-               if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS)
+               }
+               if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) {
+                       kfree_skb(skb);
                        return -EINVAL;
-               if (sk->sk_no_check_tx)
+               }
+               if (sk->sk_no_check_tx) {
+                       kfree_skb(skb);
                        return -EINVAL;
+               }
                if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite ||
-                   dst_xfrm(skb_dst(skb)))
+                   dst_xfrm(skb_dst(skb))) {
+                       kfree_skb(skb);
                        return -EIO;
+               }
 
                skb_shinfo(skb)->gso_size = cork->gso_size;
                skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
@@ -1918,7 +1928,7 @@ void udp_lib_rehash(struct sock *sk, u16 newhash)
 }
 EXPORT_SYMBOL(udp_lib_rehash);
 
-static void udp_v4_rehash(struct sock *sk)
+void udp_v4_rehash(struct sock *sk)
 {
        u16 new_hash = ipv4_portaddr_hash(sock_net(sk),
                                          inet_sk(sk)->inet_rcv_saddr,
index 3226726..6b2fa77 100644 (file)
@@ -10,6 +10,7 @@ int __udp4_lib_rcv(struct sk_buff *, struct udp_table *, int);
 int __udp4_lib_err(struct sk_buff *, u32, struct udp_table *);
 
 int udp_v4_get_port(struct sock *sk, unsigned short snum);
+void udp_v4_rehash(struct sock *sk);
 
 int udp_setsockopt(struct sock *sk, int level, int optname,
                   char __user *optval, unsigned int optlen);
index 39c7f17..3c94b8f 100644 (file)
@@ -53,6 +53,7 @@ struct proto  udplite_prot = {
        .sendpage          = udp_sendpage,
        .hash              = udp_lib_hash,
        .unhash            = udp_lib_unhash,
+       .rehash            = udp_v4_rehash,
        .get_port          = udp_v4_get_port,
        .memory_allocated  = &udp_memory_allocated,
        .sysctl_mem        = sysctl_udp_mem,
index 8eeec6e..72ffd3d 100644 (file)
@@ -1165,7 +1165,8 @@ check_cleanup_prefix_route(struct inet6_ifaddr *ifp, unsigned long *expires)
        list_for_each_entry(ifa, &idev->addr_list, if_list) {
                if (ifa == ifp)
                        continue;
-               if (!ipv6_prefix_equal(&ifa->addr, &ifp->addr,
+               if (ifa->prefix_len != ifp->prefix_len ||
+                   !ipv6_prefix_equal(&ifa->addr, &ifp->addr,
                                       ifp->prefix_len))
                        continue;
                if (ifa->flags & (IFA_F_PERMANENT | IFA_F_NOPREFIXROUTE))
@@ -3495,8 +3496,8 @@ static int addrconf_notify(struct notifier_block *this, unsigned long event,
 
                        if (!addrconf_link_ready(dev)) {
                                /* device is not ready yet. */
-                               pr_info("ADDRCONF(NETDEV_UP): %s: link is not ready\n",
-                                       dev->name);
+                               pr_debug("ADDRCONF(NETDEV_UP): %s: link is not ready\n",
+                                        dev->name);
                                break;
                        }
 
@@ -5120,6 +5121,8 @@ static int inet6_dump_addr(struct sk_buff *skb, struct netlink_callback *cb,
                        if (idev) {
                                err = in6_dump_addrs(idev, skb, cb, s_ip_idx,
                                                     &fillargs);
+                               if (err > 0)
+                                       err = 0;
                        }
                        goto put_tgt_net;
                }
@@ -5154,7 +5157,7 @@ put_tgt_net:
        if (fillargs.netnsid >= 0)
                put_net(tgt_net);
 
-       return err < 0 ? err : skb->len;
+       return skb->len ? : err;
 }
 
 static int inet6_dump_ifaddr(struct sk_buff *skb, struct netlink_callback *cb)
index 0bfb6cc..d99753b 100644 (file)
@@ -310,6 +310,7 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
 
        /* Check if the address belongs to the host. */
        if (addr_type == IPV6_ADDR_MAPPED) {
+               struct net_device *dev = NULL;
                int chk_addr_ret;
 
                /* Binding to v4-mapped address on a v6-only socket
@@ -320,9 +321,20 @@ static int __inet6_bind(struct sock *sk, struct sockaddr *uaddr, int addr_len,
                        goto out;
                }
 
+               rcu_read_lock();
+               if (sk->sk_bound_dev_if) {
+                       dev = dev_get_by_index_rcu(net, sk->sk_bound_dev_if);
+                       if (!dev) {
+                               err = -ENODEV;
+                               goto out_unlock;
+                       }
+               }
+
                /* Reproduce AF_INET checks to make the bindings consistent */
                v4addr = addr->sin6_addr.s6_addr32[3];
-               chk_addr_ret = inet_addr_type(net, v4addr);
+               chk_addr_ret = inet_addr_type_dev_table(net, dev, v4addr);
+               rcu_read_unlock();
+
                if (!inet_can_nonlocal_bind(net, inet) &&
                    v4addr != htonl(INADDR_ANY) &&
                    chk_addr_ret != RTN_LOCAL &&
index bde08aa..ee4a4e5 100644 (file)
@@ -341,6 +341,7 @@ void ipv6_local_error(struct sock *sk, int err, struct flowi6 *fl6, u32 info)
        skb_reset_network_header(skb);
        iph = ipv6_hdr(skb);
        iph->daddr = fl6->daddr;
+       ip6_flow_hdr(iph, 0, 0);
 
        serr = SKB_EXT_ERR(skb);
        serr->ee.ee_errno = err;
@@ -700,17 +701,15 @@ void ip6_datagram_recv_specific_ctl(struct sock *sk, struct msghdr *msg,
        }
        if (np->rxopt.bits.rxorigdstaddr) {
                struct sockaddr_in6 sin6;
-               __be16 *ports;
-               int end;
+               __be16 _ports[2], *ports;
 
-               end = skb_transport_offset(skb) + 4;
-               if (end <= 0 || pskb_may_pull(skb, end)) {
+               ports = skb_header_pointer(skb, skb_transport_offset(skb),
+                                          sizeof(_ports), &_ports);
+               if (ports) {
                        /* All current transport protocols have the port numbers in the
                         * first four bytes of the transport header and this function is
                         * written with this assumption in mind.
                         */
-                       ports = (__be16 *)skb_transport_header(skb);
-
                        sin6.sin6_family = AF_INET6;
                        sin6.sin6_addr = ipv6_hdr(skb)->daddr;
                        sin6.sin6_port = ports[1];
index 5afe9f8..239d4a6 100644 (file)
@@ -296,7 +296,7 @@ int esp6_output_head(struct xfrm_state *x, struct sk_buff *skb, struct esp_info
                        skb->len += tailen;
                        skb->data_len += tailen;
                        skb->truesize += tailen;
-                       if (sk)
+                       if (sk && sk_fullsock(sk))
                                refcount_add(tailen, &sk->sk_wmem_alloc);
 
                        goto out;
index bd675c6..867474a 100644 (file)
@@ -72,7 +72,7 @@ static int gue6_build_header(struct sk_buff *skb, struct ip_tunnel_encap *e,
 
 static int gue6_err_proto_handler(int proto, struct sk_buff *skb,
                                  struct inet6_skb_parm *opt,
-                                 u8 type, u8 code, int offset, u32 info)
+                                 u8 type, u8 code, int offset, __be32 info)
 {
        const struct inet6_protocol *ipprot;
 
@@ -90,10 +90,11 @@ static int gue6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 {
        int transport_offset = skb_transport_offset(skb);
        struct guehdr *guehdr;
-       size_t optlen;
+       size_t len, optlen;
        int ret;
 
-       if (skb->len < sizeof(struct udphdr) + sizeof(struct guehdr))
+       len = sizeof(struct udphdr) + sizeof(struct guehdr);
+       if (!pskb_may_pull(skb, len))
                return -EINVAL;
 
        guehdr = (struct guehdr *)&udp_hdr(skb)[1];
@@ -128,9 +129,21 @@ static int gue6_err(struct sk_buff *skb, struct inet6_skb_parm *opt,
 
        optlen = guehdr->hlen << 2;
 
+       if (!pskb_may_pull(skb, len + optlen))
+               return -EINVAL;
+
+       guehdr = (struct guehdr *)&udp_hdr(skb)[1];
        if (validate_gue_flags(guehdr, optlen))
                return -EINVAL;
 
+       /* Handling exceptions for direct UDP encapsulation in GUE would lead to
+        * recursion. Besides, this kind of encapsulation can't even be
+        * configured currently. Discard this.
+        */
+       if (guehdr->proto_ctype == IPPROTO_UDP ||
+           guehdr->proto_ctype == IPPROTO_UDPLITE)
+               return -EOPNOTSUPP;
+
        skb_set_transport_header(skb, -(int)sizeof(struct icmp6hdr));
        ret = gue6_err_proto_handler(guehdr->proto_ctype, skb,
                                     opt, type, code, offset, info);
index 5d7aa2c..bbcdfd2 100644 (file)
@@ -423,10 +423,10 @@ static int icmp6_iif(const struct sk_buff *skb)
 static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
                       const struct in6_addr *force_saddr)
 {
-       struct net *net = dev_net(skb->dev);
        struct inet6_dev *idev = NULL;
        struct ipv6hdr *hdr = ipv6_hdr(skb);
        struct sock *sk;
+       struct net *net;
        struct ipv6_pinfo *np;
        const struct in6_addr *saddr = NULL;
        struct dst_entry *dst;
@@ -437,12 +437,16 @@ static void icmp6_send(struct sk_buff *skb, u8 type, u8 code, __u32 info,
        int iif = 0;
        int addr_type = 0;
        int len;
-       u32 mark = IP6_REPLY_MARK(net, skb->mark);
+       u32 mark;
 
        if ((u8 *)hdr < skb->head ||
            (skb_network_header(skb) + sizeof(*hdr)) > skb_tail_pointer(skb))
                return;
 
+       if (!skb->dev)
+               return;
+       net = dev_net(skb->dev);
+       mark = IP6_REPLY_MARK(net, skb->mark);
        /*
         *      Make sure we respect the rules
         *      i.e. RFC 1885 2.4(e)
index 09d0826..26f25b6 100644 (file)
@@ -534,13 +534,9 @@ static int ip6erspan_rcv(struct sk_buff *skb, int gre_hdr_len,
        struct ip6_tnl *tunnel;
        u8 ver;
 
-       if (unlikely(!pskb_may_pull(skb, sizeof(*ershdr))))
-               return PACKET_REJECT;
-
        ipv6h = ipv6_hdr(skb);
        ershdr = (struct erspan_base_hdr *)skb->data;
        ver = ershdr->ver;
-       tpi->key = cpu_to_be32(get_session_id(ershdr));
 
        tunnel = ip6gre_tunnel_lookup(skb->dev,
                                      &ipv6h->saddr, &ipv6h->daddr, tpi->key,
@@ -922,6 +918,7 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
        __u8 dsfield = false;
        struct flowi6 fl6;
        int err = -EINVAL;
+       __be16 proto;
        __u32 mtu;
        int nhoff;
        int thoff;
@@ -1035,8 +1032,9 @@ static netdev_tx_t ip6erspan_tunnel_xmit(struct sk_buff *skb,
        }
 
        /* Push GRE header. */
-       gre_build_header(skb, 8, TUNNEL_SEQ,
-                        htons(ETH_P_ERSPAN), 0, htonl(t->o_seqno++));
+       proto = (t->parms.erspan_ver == 1) ? htons(ETH_P_ERSPAN)
+                                          : htons(ETH_P_ERSPAN2);
+       gre_build_header(skb, 8, TUNNEL_SEQ, proto, 0, htonl(t->o_seqno++));
 
        /* TooBig packet may have updated dst->dev's mtu */
        if (!t->parms.collect_md && dst && dst_mtu(dst) > dst->dev->mtu)
@@ -1169,6 +1167,10 @@ static void ip6gre_tnl_copy_tnl_parm(struct ip6_tnl *t,
        t->parms.i_flags = p->i_flags;
        t->parms.o_flags = p->o_flags;
        t->parms.fwmark = p->fwmark;
+       t->parms.erspan_ver = p->erspan_ver;
+       t->parms.index = p->index;
+       t->parms.dir = p->dir;
+       t->parms.hwid = p->hwid;
        dst_cache_reset(&t->dst_cache);
 }
 
@@ -1717,6 +1719,27 @@ static int ip6erspan_tap_validate(struct nlattr *tb[], struct nlattr *data[],
        return 0;
 }
 
+static void ip6erspan_set_version(struct nlattr *data[],
+                                 struct __ip6_tnl_parm *parms)
+{
+       if (!data)
+               return;
+
+       parms->erspan_ver = 1;
+       if (data[IFLA_GRE_ERSPAN_VER])
+               parms->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]);
+
+       if (parms->erspan_ver == 1) {
+               if (data[IFLA_GRE_ERSPAN_INDEX])
+                       parms->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
+       } else if (parms->erspan_ver == 2) {
+               if (data[IFLA_GRE_ERSPAN_DIR])
+                       parms->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]);
+               if (data[IFLA_GRE_ERSPAN_HWID])
+                       parms->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]);
+       }
+}
+
 static void ip6gre_netlink_parms(struct nlattr *data[],
                                struct __ip6_tnl_parm *parms)
 {
@@ -1765,20 +1788,6 @@ static void ip6gre_netlink_parms(struct nlattr *data[],
 
        if (data[IFLA_GRE_COLLECT_METADATA])
                parms->collect_md = true;
-
-       parms->erspan_ver = 1;
-       if (data[IFLA_GRE_ERSPAN_VER])
-               parms->erspan_ver = nla_get_u8(data[IFLA_GRE_ERSPAN_VER]);
-
-       if (parms->erspan_ver == 1) {
-               if (data[IFLA_GRE_ERSPAN_INDEX])
-                       parms->index = nla_get_u32(data[IFLA_GRE_ERSPAN_INDEX]);
-       } else if (parms->erspan_ver == 2) {
-               if (data[IFLA_GRE_ERSPAN_DIR])
-                       parms->dir = nla_get_u8(data[IFLA_GRE_ERSPAN_DIR]);
-               if (data[IFLA_GRE_ERSPAN_HWID])
-                       parms->hwid = nla_get_u16(data[IFLA_GRE_ERSPAN_HWID]);
-       }
 }
 
 static int ip6gre_tap_init(struct net_device *dev)
@@ -2025,9 +2034,9 @@ static int ip6gre_changelink(struct net_device *dev, struct nlattr *tb[],
                             struct nlattr *data[],
                             struct netlink_ext_ack *extack)
 {
-       struct ip6gre_net *ign = net_generic(dev_net(dev), ip6gre_net_id);
+       struct ip6_tnl *t = netdev_priv(dev);
+       struct ip6gre_net *ign = net_generic(t->net, ip6gre_net_id);
        struct __ip6_tnl_parm p;
-       struct ip6_tnl *t;
 
        t = ip6gre_changelink_common(dev, tb, data, &p, extack);
        if (IS_ERR(t))
@@ -2096,12 +2105,31 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)
 {
        struct ip6_tnl *t = netdev_priv(dev);
        struct __ip6_tnl_parm *p = &t->parms;
+       __be16 o_flags = p->o_flags;
+
+       if (p->erspan_ver == 1 || p->erspan_ver == 2) {
+               if (!p->collect_md)
+                       o_flags |= TUNNEL_KEY;
+
+               if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, p->erspan_ver))
+                       goto nla_put_failure;
+
+               if (p->erspan_ver == 1) {
+                       if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, p->index))
+                               goto nla_put_failure;
+               } else {
+                       if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, p->dir))
+                               goto nla_put_failure;
+                       if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, p->hwid))
+                               goto nla_put_failure;
+               }
+       }
 
        if (nla_put_u32(skb, IFLA_GRE_LINK, p->link) ||
            nla_put_be16(skb, IFLA_GRE_IFLAGS,
                         gre_tnl_flags_to_gre_flags(p->i_flags)) ||
            nla_put_be16(skb, IFLA_GRE_OFLAGS,
-                        gre_tnl_flags_to_gre_flags(p->o_flags)) ||
+                        gre_tnl_flags_to_gre_flags(o_flags)) ||
            nla_put_be32(skb, IFLA_GRE_IKEY, p->i_key) ||
            nla_put_be32(skb, IFLA_GRE_OKEY, p->o_key) ||
            nla_put_in6_addr(skb, IFLA_GRE_LOCAL, &p->laddr) ||
@@ -2110,8 +2138,7 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)
            nla_put_u8(skb, IFLA_GRE_ENCAP_LIMIT, p->encap_limit) ||
            nla_put_be32(skb, IFLA_GRE_FLOWINFO, p->flowinfo) ||
            nla_put_u32(skb, IFLA_GRE_FLAGS, p->flags) ||
-           nla_put_u32(skb, IFLA_GRE_FWMARK, p->fwmark) ||
-           nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, p->index))
+           nla_put_u32(skb, IFLA_GRE_FWMARK, p->fwmark))
                goto nla_put_failure;
 
        if (nla_put_u16(skb, IFLA_GRE_ENCAP_TYPE,
@@ -2129,19 +2156,6 @@ static int ip6gre_fill_info(struct sk_buff *skb, const struct net_device *dev)
                        goto nla_put_failure;
        }
 
-       if (nla_put_u8(skb, IFLA_GRE_ERSPAN_VER, p->erspan_ver))
-               goto nla_put_failure;
-
-       if (p->erspan_ver == 1) {
-               if (nla_put_u32(skb, IFLA_GRE_ERSPAN_INDEX, p->index))
-                       goto nla_put_failure;
-       } else if (p->erspan_ver == 2) {
-               if (nla_put_u8(skb, IFLA_GRE_ERSPAN_DIR, p->dir))
-                       goto nla_put_failure;
-               if (nla_put_u16(skb, IFLA_GRE_ERSPAN_HWID, p->hwid))
-                       goto nla_put_failure;
-       }
-
        return 0;
 
 nla_put_failure:
@@ -2196,6 +2210,7 @@ static int ip6erspan_newlink(struct net *src_net, struct net_device *dev,
        int err;
 
        ip6gre_netlink_parms(data, &nt->parms);
+       ip6erspan_set_version(data, &nt->parms);
        ign = net_generic(net, ip6gre_net_id);
 
        if (nt->parms.collect_md) {
@@ -2241,6 +2256,7 @@ static int ip6erspan_changelink(struct net_device *dev, struct nlattr *tb[],
        if (IS_ERR(t))
                return PTR_ERR(t);
 
+       ip6erspan_set_version(data, &p);
        ip6gre_tunnel_unlink_md(ign, t);
        ip6gre_tunnel_unlink(ign, t);
        ip6erspan_tnl_change(t, &p, !tb[IFLA_MTU]);
index 30337b3..cc01aa3 100644 (file)
@@ -1516,6 +1516,9 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
                        continue;
                rhltable_remove(&mrt->mfc_hash, &c->mnode, ip6mr_rht_params);
                list_del_rcu(&c->list);
+               call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
+                                              FIB_EVENT_ENTRY_DEL,
+                                              (struct mfc6_cache *)c, mrt->id);
                mr6_netlink_event(mrt, (struct mfc6_cache *)c, RTM_DELROUTE);
                mr_cache_put(c);
        }
@@ -1524,10 +1527,6 @@ static void mroute_clean_tables(struct mr_table *mrt, bool all)
                spin_lock_bh(&mfc_unres_lock);
                list_for_each_entry_safe(c, tmp, &mrt->mfc_unres_queue, list) {
                        list_del(&c->list);
-                       call_ip6mr_mfc_entry_notifiers(read_pnet(&mrt->net),
-                                                      FIB_EVENT_ENTRY_DEL,
-                                                      (struct mfc6_cache *)c,
-                                                      mrt->id);
                        mr6_netlink_event(mrt, (struct mfc6_cache *)c,
                                          RTM_DELROUTE);
                        ip6mr_destroy_unres(mrt, (struct mfc6_cache *)c);
index 8b075f0..6d0b1f3 100644 (file)
@@ -23,9 +23,11 @@ int ip6_route_me_harder(struct net *net, struct sk_buff *skb)
        struct sock *sk = sk_to_full_sk(skb->sk);
        unsigned int hh_len;
        struct dst_entry *dst;
+       int strict = (ipv6_addr_type(&iph->daddr) &
+                     (IPV6_ADDR_MULTICAST | IPV6_ADDR_LINKLOCAL));
        struct flowi6 fl6 = {
                .flowi6_oif = sk && sk->sk_bound_dev_if ? sk->sk_bound_dev_if :
-                       rt6_need_strict(&iph->daddr) ? skb_dst(skb)->dev->ifindex : 0,
+                       strict ? skb_dst(skb)->dev->ifindex : 0,
                .flowi6_mark = skb->mark,
                .flowi6_uid = sock_net_uid(net, sk),
                .daddr = iph->daddr,
index 2302244..7a41ee3 100644 (file)
@@ -226,6 +226,7 @@ int nf_nat_icmpv6_reply_translation(struct sk_buff *skb,
        }
 
        nf_ct_invert_tuplepr(&target, &ct->tuplehash[!dir].tuple);
+       target.dst.protonum = IPPROTO_ICMPV6;
        if (!nf_nat_ipv6_manip_pkt(skb, 0, &target, manip))
                return 0;
 
index 40b225f..ce15dc4 100644 (file)
@@ -1274,18 +1274,29 @@ static DEFINE_SPINLOCK(rt6_exception_lock);
 static void rt6_remove_exception(struct rt6_exception_bucket *bucket,
                                 struct rt6_exception *rt6_ex)
 {
+       struct fib6_info *from;
        struct net *net;
 
        if (!bucket || !rt6_ex)
                return;
 
        net = dev_net(rt6_ex->rt6i->dst.dev);
+       net->ipv6.rt6_stats->fib_rt_cache--;
+
+       /* purge completely the exception to allow releasing the held resources:
+        * some [sk] cache may keep the dst around for unlimited time
+        */
+       from = rcu_dereference_protected(rt6_ex->rt6i->from,
+                                        lockdep_is_held(&rt6_exception_lock));
+       rcu_assign_pointer(rt6_ex->rt6i->from, NULL);
+       fib6_info_release(from);
+       dst_dev_put(&rt6_ex->rt6i->dst);
+
        hlist_del_rcu(&rt6_ex->hlist);
        dst_release(&rt6_ex->rt6i->dst);
        kfree_rcu(rt6_ex, rcu);
        WARN_ON_ONCE(!bucket->depth);
        bucket->depth--;
-       net->ipv6.rt6_stats->fib_rt_cache--;
 }
 
 /* Remove oldest rt6_ex in bucket and free the memory
@@ -1599,15 +1610,15 @@ static int rt6_remove_exception_rt(struct rt6_info *rt)
 static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
 {
        struct rt6_exception_bucket *bucket;
-       struct fib6_info *from = rt->from;
        struct in6_addr *src_key = NULL;
        struct rt6_exception *rt6_ex;
-
-       if (!from ||
-           !(rt->rt6i_flags & RTF_CACHE))
-               return;
+       struct fib6_info *from;
 
        rcu_read_lock();
+       from = rcu_dereference(rt->from);
+       if (!from || !(rt->rt6i_flags & RTF_CACHE))
+               goto unlock;
+
        bucket = rcu_dereference(from->rt6i_exception_bucket);
 
 #ifdef CONFIG_IPV6_SUBTREES
@@ -1626,6 +1637,7 @@ static void rt6_update_exception_stamp_rt(struct rt6_info *rt)
        if (rt6_ex)
                rt6_ex->stamp = jiffies;
 
+unlock:
        rcu_read_unlock();
 }
 
@@ -2742,20 +2754,24 @@ static int ip6_route_check_nh_onlink(struct net *net,
        u32 tbid = l3mdev_fib_table(dev) ? : RT_TABLE_MAIN;
        const struct in6_addr *gw_addr = &cfg->fc_gateway;
        u32 flags = RTF_LOCAL | RTF_ANYCAST | RTF_REJECT;
+       struct fib6_info *from;
        struct rt6_info *grt;
        int err;
 
        err = 0;
        grt = ip6_nh_lookup_table(net, cfg, gw_addr, tbid, 0);
        if (grt) {
+               rcu_read_lock();
+               from = rcu_dereference(grt->from);
                if (!grt->dst.error &&
                    /* ignore match if it is the default route */
-                   grt->from && !ipv6_addr_any(&grt->from->fib6_dst.addr) &&
+                   from && !ipv6_addr_any(&from->fib6_dst.addr) &&
                    (grt->rt6i_flags & flags || dev != grt->dst.dev)) {
                        NL_SET_ERR_MSG(extack,
                                       "Nexthop has invalid gateway or device mismatch");
                        err = -EINVAL;
                }
+               rcu_read_unlock();
 
                ip6_rt_put(grt);
        }
@@ -4251,17 +4267,6 @@ struct rt6_nh {
        struct list_head next;
 };
 
-static void ip6_print_replace_route_err(struct list_head *rt6_nh_list)
-{
-       struct rt6_nh *nh;
-
-       list_for_each_entry(nh, rt6_nh_list, next) {
-               pr_warn("IPV6: multipath route replace failed (check consistency of installed routes): %pI6c nexthop %pI6c ifi %d\n",
-                       &nh->r_cfg.fc_dst, &nh->r_cfg.fc_gateway,
-                       nh->r_cfg.fc_ifindex);
-       }
-}
-
 static int ip6_route_info_append(struct net *net,
                                 struct list_head *rt6_nh_list,
                                 struct fib6_info *rt,
@@ -4407,7 +4412,8 @@ static int ip6_route_multipath_add(struct fib6_config *cfg,
                nh->fib6_info = NULL;
                if (err) {
                        if (replace && nhn)
-                               ip6_print_replace_route_err(&rt6_nh_list);
+                               NL_SET_ERR_MSG_MOD(extack,
+                                                  "multipath route replace failed (check consistency of installed routes)");
                        err_nh = nh;
                        goto add_errout;
                }
@@ -4659,7 +4665,7 @@ static int rt6_fill_node(struct net *net, struct sk_buff *skb,
                table = rt->fib6_table->tb6_id;
        else
                table = RT6_TABLE_UNSPEC;
-       rtm->rtm_table = table;
+       rtm->rtm_table = table < 256 ? table : RT_TABLE_COMPAT;
        if (nla_put_u32(skb, RTA_TABLE, table))
                goto nla_put_failure;
 
index 8d0ba75..9b2f272 100644 (file)
@@ -221,9 +221,7 @@ static int seg6_genl_get_tunsrc(struct sk_buff *skb, struct genl_info *info)
        rcu_read_unlock();
 
        genlmsg_end(msg, hdr);
-       genlmsg_reply(msg, info);
-
-       return 0;
+       return genlmsg_reply(msg, info);
 
 nla_put_failure:
        rcu_read_unlock();
index 8181ee7..ee5403c 100644 (file)
@@ -146,6 +146,8 @@ int seg6_do_srh_encap(struct sk_buff *skb, struct ipv6_sr_hdr *osrh, int proto)
        } else {
                ip6_flow_hdr(hdr, 0, flowlabel);
                hdr->hop_limit = ip6_dst_hoplimit(skb_dst(skb));
+
+               memset(IP6CB(skb), 0, sizeof(*IP6CB(skb)));
        }
 
        hdr->nexthdr = NEXTHDR_ROUTING;
index 1e03305..e8a1dab 100644 (file)
@@ -546,7 +546,8 @@ static int ipip6_err(struct sk_buff *skb, u32 info)
        }
 
        err = 0;
-       if (!ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len))
+       if (__in6_dev_get(skb->dev) &&
+           !ip6_err_gen_icmpv6_unreach(skb, iph->ihl * 4, type, data_len))
                goto out;
 
        if (t->parms.iph.daddr == 0)
index 9cbf363..b444483 100644 (file)
@@ -102,7 +102,7 @@ int udp_v6_get_port(struct sock *sk, unsigned short snum)
        return udp_lib_get_port(sk, snum, hash2_nulladdr);
 }
 
-static void udp_v6_rehash(struct sock *sk)
+void udp_v6_rehash(struct sock *sk)
 {
        u16 new_hash = ipv6_portaddr_hash(sock_net(sk),
                                          &sk->sk_v6_rcv_saddr,
@@ -288,8 +288,8 @@ int udpv6_recvmsg(struct sock *sk, struct msghdr *msg, size_t len,
        int peeked, peeking, off;
        int err;
        int is_udplite = IS_UDPLITE(sk);
+       struct udp_mib __percpu *mib;
        bool checksum_valid = false;
-       struct udp_mib *mib;
        int is_udp4;
 
        if (flags & MSG_ERRQUEUE)
@@ -420,17 +420,19 @@ EXPORT_SYMBOL(udpv6_encap_enable);
  */
 static int __udp6_lib_err_encap_no_sk(struct sk_buff *skb,
                                      struct inet6_skb_parm *opt,
-                                     u8 type, u8 code, int offset, u32 info)
+                                     u8 type, u8 code, int offset, __be32 info)
 {
        int i;
 
        for (i = 0; i < MAX_IPTUN_ENCAP_OPS; i++) {
                int (*handler)(struct sk_buff *skb, struct inet6_skb_parm *opt,
-                              u8 type, u8 code, int offset, u32 info);
+                              u8 type, u8 code, int offset, __be32 info);
+               const struct ip6_tnl_encap_ops *encap;
 
-               if (!ip6tun_encaps[i])
+               encap = rcu_dereference(ip6tun_encaps[i]);
+               if (!encap)
                        continue;
-               handler = rcu_dereference(ip6tun_encaps[i]->err_handler);
+               handler = encap->err_handler;
                if (handler && !handler(skb, opt, type, code, offset, info))
                        return 0;
        }
@@ -1132,15 +1134,23 @@ static int udp_v6_send_skb(struct sk_buff *skb, struct flowi6 *fl6,
                const int hlen = skb_network_header_len(skb) +
                                 sizeof(struct udphdr);
 
-               if (hlen + cork->gso_size > cork->fragsize)
+               if (hlen + cork->gso_size > cork->fragsize) {
+                       kfree_skb(skb);
                        return -EINVAL;
-               if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS)
+               }
+               if (skb->len > cork->gso_size * UDP_MAX_SEGMENTS) {
+                       kfree_skb(skb);
                        return -EINVAL;
-               if (udp_sk(sk)->no_check6_tx)
+               }
+               if (udp_sk(sk)->no_check6_tx) {
+                       kfree_skb(skb);
                        return -EINVAL;
+               }
                if (skb->ip_summed != CHECKSUM_PARTIAL || is_udplite ||
-                   dst_xfrm(skb_dst(skb)))
+                   dst_xfrm(skb_dst(skb))) {
+                       kfree_skb(skb);
                        return -EIO;
+               }
 
                skb_shinfo(skb)->gso_size = cork->gso_size;
                skb_shinfo(skb)->gso_type = SKB_GSO_UDP_L4;
@@ -1390,10 +1400,7 @@ do_udp_sendmsg:
        ipc6.opt = opt;
 
        fl6.flowi6_proto = sk->sk_protocol;
-       if (!ipv6_addr_any(daddr))
-               fl6.daddr = *daddr;
-       else
-               fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
+       fl6.daddr = *daddr;
        if (ipv6_addr_any(&fl6.saddr) && !ipv6_addr_any(&np->saddr))
                fl6.saddr = np->saddr;
        fl6.fl6_sport = inet->inet_sport;
@@ -1421,6 +1428,9 @@ do_udp_sendmsg:
                }
        }
 
+       if (ipv6_addr_any(&fl6.daddr))
+               fl6.daddr.s6_addr[15] = 0x1; /* :: means loopback (BSD'ism) */
+
        final_p = fl6_update_dst(&fl6, opt, &final);
        if (final_p)
                connected = false;
index 5730e65..20e324b 100644 (file)
@@ -13,6 +13,7 @@ int __udp6_lib_err(struct sk_buff *, struct inet6_skb_parm *, u8, u8, int,
                   __be32, struct udp_table *);
 
 int udp_v6_get_port(struct sock *sk, unsigned short snum);
+void udp_v6_rehash(struct sock *sk);
 
 int udpv6_getsockopt(struct sock *sk, int level, int optname,
                     char __user *optval, int __user *optlen);
index a125aeb..f359078 100644 (file)
@@ -49,6 +49,7 @@ struct proto udplitev6_prot = {
        .recvmsg           = udpv6_recvmsg,
        .hash              = udp_lib_hash,
        .unhash            = udp_lib_unhash,
+       .rehash            = udp_v6_rehash,
        .get_port          = udp_v6_get_port,
        .memory_allocated  = &udp_memory_allocated,
        .sysctl_mem        = sysctl_udp_mem,
index f5b4feb..bc65db7 100644 (file)
@@ -344,8 +344,8 @@ static void __net_exit xfrm6_tunnel_net_exit(struct net *net)
        struct xfrm6_tunnel_net *xfrm6_tn = xfrm6_tunnel_pernet(net);
        unsigned int i;
 
-       xfrm_state_flush(net, IPSEC_PROTO_ANY, false);
        xfrm_flush_gc();
+       xfrm_state_flush(net, IPSEC_PROTO_ANY, false, true);
 
        for (i = 0; i < XFRM6_TUNNEL_SPI_BYADDR_HSIZE; i++)
                WARN_ON_ONCE(!hlist_empty(&xfrm6_tn->spi_byaddr[i]));
index 655c787..5651c29 100644 (file)
@@ -196,30 +196,22 @@ static int pfkey_release(struct socket *sock)
        return 0;
 }
 
-static int pfkey_broadcast_one(struct sk_buff *skb, struct sk_buff **skb2,
-                              gfp_t allocation, struct sock *sk)
+static int pfkey_broadcast_one(struct sk_buff *skb, gfp_t allocation,
+                              struct sock *sk)
 {
        int err = -ENOBUFS;
 
-       sock_hold(sk);
-       if (*skb2 == NULL) {
-               if (refcount_read(&skb->users) != 1) {
-                       *skb2 = skb_clone(skb, allocation);
-               } else {
-                       *skb2 = skb;
-                       refcount_inc(&skb->users);
-               }
-       }
-       if (*skb2 != NULL) {
-               if (atomic_read(&sk->sk_rmem_alloc) <= sk->sk_rcvbuf) {
-                       skb_set_owner_r(*skb2, sk);
-                       skb_queue_tail(&sk->sk_receive_queue, *skb2);
-                       sk->sk_data_ready(sk);
-                       *skb2 = NULL;
-                       err = 0;
-               }
+       if (atomic_read(&sk->sk_rmem_alloc) > sk->sk_rcvbuf)
+               return err;
+
+       skb = skb_clone(skb, allocation);
+
+       if (skb) {
+               skb_set_owner_r(skb, sk);
+               skb_queue_tail(&sk->sk_receive_queue, skb);
+               sk->sk_data_ready(sk);
+               err = 0;
        }
-       sock_put(sk);
        return err;
 }
 
@@ -234,7 +226,6 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
 {
        struct netns_pfkey *net_pfkey = net_generic(net, pfkey_net_id);
        struct sock *sk;
-       struct sk_buff *skb2 = NULL;
        int err = -ESRCH;
 
        /* XXX Do we need something like netlink_overrun?  I think
@@ -253,7 +244,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
                 * socket.
                 */
                if (pfk->promisc)
-                       pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
+                       pfkey_broadcast_one(skb, GFP_ATOMIC, sk);
 
                /* the exact target will be processed later */
                if (sk == one_sk)
@@ -268,7 +259,7 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
                                continue;
                }
 
-               err2 = pfkey_broadcast_one(skb, &skb2, GFP_ATOMIC, sk);
+               err2 = pfkey_broadcast_one(skb, GFP_ATOMIC, sk);
 
                /* Error is cleared after successful sending to at least one
                 * registered KM */
@@ -278,9 +269,8 @@ static int pfkey_broadcast(struct sk_buff *skb, gfp_t allocation,
        rcu_read_unlock();
 
        if (one_sk != NULL)
-               err = pfkey_broadcast_one(skb, &skb2, allocation, one_sk);
+               err = pfkey_broadcast_one(skb, allocation, one_sk);
 
-       kfree_skb(skb2);
        kfree_skb(skb);
        return err;
 }
@@ -1783,7 +1773,7 @@ static int pfkey_flush(struct sock *sk, struct sk_buff *skb, const struct sadb_m
        if (proto == 0)
                return -EINVAL;
 
-       err = xfrm_state_flush(net, proto, true);
+       err = xfrm_state_flush(net, proto, true, false);
        err2 = unicast_flush_resp(sk, hdr);
        if (err || err2) {
                if (err == -ESRCH) /* empty table - go quietly */
index 26f1d43..fed6bec 100644 (file)
@@ -83,8 +83,7 @@
 #define L2TP_SLFLAG_S     0x40000000
 #define L2TP_SL_SEQ_MASK   0x00ffffff
 
-#define L2TP_HDR_SIZE_SEQ              10
-#define L2TP_HDR_SIZE_NOSEQ            6
+#define L2TP_HDR_SIZE_MAX              14
 
 /* Default trace flags */
 #define L2TP_DEFAULT_DEBUG_FLAGS       0
@@ -808,7 +807,7 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
        __skb_pull(skb, sizeof(struct udphdr));
 
        /* Short packet? */
-       if (!pskb_may_pull(skb, L2TP_HDR_SIZE_SEQ)) {
+       if (!pskb_may_pull(skb, L2TP_HDR_SIZE_MAX)) {
                l2tp_info(tunnel, L2TP_MSG_DATA,
                          "%s: recv short packet (len=%d)\n",
                          tunnel->name, skb->len);
@@ -884,6 +883,10 @@ static int l2tp_udp_recv_core(struct l2tp_tunnel *tunnel, struct sk_buff *skb)
                goto error;
        }
 
+       if (tunnel->version == L2TP_HDR_VER_3 &&
+           l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
+               goto error;
+
        l2tp_recv_common(session, skb, ptr, optr, hdrflags, length);
        l2tp_session_dec_refcount(session);
 
index 9c9afe9..b2ce902 100644 (file)
@@ -301,6 +301,26 @@ static inline bool l2tp_tunnel_uses_xfrm(const struct l2tp_tunnel *tunnel)
 }
 #endif
 
+static inline int l2tp_v3_ensure_opt_in_linear(struct l2tp_session *session, struct sk_buff *skb,
+                                              unsigned char **ptr, unsigned char **optr)
+{
+       int opt_len = session->peer_cookie_len + l2tp_get_l2specific_len(session);
+
+       if (opt_len > 0) {
+               int off = *ptr - *optr;
+
+               if (!pskb_may_pull(skb, off + opt_len))
+                       return -1;
+
+               if (skb->data != *optr) {
+                       *optr = skb->data;
+                       *ptr = skb->data + off;
+               }
+       }
+
+       return 0;
+}
+
 #define l2tp_printk(ptr, type, func, fmt, ...)                         \
 do {                                                                   \
        if (((ptr)->debug) & (type))                                    \
index 35f6f86..d4c6052 100644 (file)
@@ -165,6 +165,9 @@ static int l2tp_ip_recv(struct sk_buff *skb)
                print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
        }
 
+       if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
+               goto discard_sess;
+
        l2tp_recv_common(session, skb, ptr, optr, 0, skb->len);
        l2tp_session_dec_refcount(session);
 
index 237f1a4..0ae6899 100644 (file)
@@ -178,6 +178,9 @@ static int l2tp_ip6_recv(struct sk_buff *skb)
                print_hex_dump_bytes("", DUMP_PREFIX_OFFSET, ptr, length);
        }
 
+       if (l2tp_v3_ensure_opt_in_linear(session, skb, &ptr, &optr))
+               goto discard_sess;
+
        l2tp_recv_common(session, skb, ptr, optr, 0, skb->len);
        l2tp_session_dec_refcount(session);
 
index 69e831b..54821fb 100644 (file)
@@ -8,7 +8,7 @@
  * Copyright 2007, Michael Wu <flamingice@sourmilk.net>
  * Copyright 2007-2010, Intel Corporation
  * Copyright(c) 2015-2017 Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018 - 2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -366,6 +366,8 @@ int ___ieee80211_stop_tx_ba_session(struct sta_info *sta, u16 tid,
 
        set_bit(HT_AGG_STATE_STOPPING, &tid_tx->state);
 
+       ieee80211_agg_stop_txq(sta, tid);
+
        spin_unlock_bh(&sta->lock);
 
        ht_dbg(sta->sdata, "Tx BA session stop requested for %pM tid %u\n",
index de65fe3..96496b2 100644 (file)
@@ -941,6 +941,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
                      BSS_CHANGED_P2P_PS |
                      BSS_CHANGED_TXPOWER;
        int err;
+       int prev_beacon_int;
 
        old = sdata_dereference(sdata->u.ap.beacon, sdata);
        if (old)
@@ -963,6 +964,7 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
 
        sdata->needed_rx_chains = sdata->local->rx_chains;
 
+       prev_beacon_int = sdata->vif.bss_conf.beacon_int;
        sdata->vif.bss_conf.beacon_int = params->beacon_interval;
 
        if (params->he_cap)
@@ -974,8 +976,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
        if (!err)
                ieee80211_vif_copy_chanctx_to_vlans(sdata, false);
        mutex_unlock(&local->mtx);
-       if (err)
+       if (err) {
+               sdata->vif.bss_conf.beacon_int = prev_beacon_int;
                return err;
+       }
 
        /*
         * Apply control port protocol, this allows us to
@@ -1490,6 +1494,10 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev,
        if (params->sta_flags_set & BIT(NL80211_STA_FLAG_TDLS_PEER))
                sta->sta.tdls = true;
 
+       if (sta->sta.tdls && sdata->vif.type == NL80211_IFTYPE_STATION &&
+           !sdata->u.mgd.associated)
+               return -EINVAL;
+
        err = sta_apply_parameters(local, sta, params);
        if (err) {
                sta_info_free(local, sta);
index 87a7299..977dea4 100644 (file)
@@ -615,13 +615,13 @@ struct ieee80211_hw *ieee80211_alloc_hw_nm(size_t priv_data_len,
         * We need a bit of data queued to build aggregates properly, so
         * instruct the TCP stack to allow more than a single ms of data
         * to be queued in the stack. The value is a bit-shift of 1
-        * second, so 8 is ~4ms of queued data. Only affects local TCP
+        * second, so 7 is ~8ms of queued data. Only affects local TCP
         * sockets.
         * This is the default, anyhow - drivers may need to override it
         * for local reasons (longer buffers, longer completion time, or
         * similar).
         */
-       local->hw.tx_sk_pacing_shift = 8;
+       local->hw.tx_sk_pacing_shift = 7;
 
        /* set up some defaults */
        local->hw.queues = 1;
index cad6592..2ec7011 100644 (file)
@@ -70,6 +70,7 @@ enum mesh_deferred_task_flags {
  * @dst: mesh path destination mac address
  * @mpp: mesh proxy mac address
  * @rhash: rhashtable list pointer
+ * @walk_list: linked list containing all mesh_path objects.
  * @gate_list: list pointer for known gates list
  * @sdata: mesh subif
  * @next_hop: mesh neighbor to which frames for this destination will be
@@ -105,6 +106,7 @@ struct mesh_path {
        u8 dst[ETH_ALEN];
        u8 mpp[ETH_ALEN];       /* used for MPP or MAP */
        struct rhash_head rhash;
+       struct hlist_node walk_list;
        struct hlist_node gate_list;
        struct ieee80211_sub_if_data *sdata;
        struct sta_info __rcu *next_hop;
@@ -133,12 +135,16 @@ struct mesh_path {
  * gate's mpath may or may not be resolved and active.
  * @gates_lock: protects updates to known_gates
  * @rhead: the rhashtable containing struct mesh_paths, keyed by dest addr
+ * @walk_head: linked list containging all mesh_path objects
+ * @walk_lock: lock protecting walk_head
  * @entries: number of entries in the table
  */
 struct mesh_table {
        struct hlist_head known_gates;
        spinlock_t gates_lock;
        struct rhashtable rhead;
+       struct hlist_head walk_head;
+       spinlock_t walk_lock;
        atomic_t entries;               /* Up to MAX_MESH_NEIGHBOURS */
 };
 
index a512562..88a6d5e 100644 (file)
@@ -59,8 +59,10 @@ static struct mesh_table *mesh_table_alloc(void)
                return NULL;
 
        INIT_HLIST_HEAD(&newtbl->known_gates);
+       INIT_HLIST_HEAD(&newtbl->walk_head);
        atomic_set(&newtbl->entries,  0);
        spin_lock_init(&newtbl->gates_lock);
+       spin_lock_init(&newtbl->walk_lock);
 
        return newtbl;
 }
@@ -249,28 +251,15 @@ mpp_path_lookup(struct ieee80211_sub_if_data *sdata, const u8 *dst)
 static struct mesh_path *
 __mesh_path_lookup_by_idx(struct mesh_table *tbl, int idx)
 {
-       int i = 0, ret;
-       struct mesh_path *mpath = NULL;
-       struct rhashtable_iter iter;
-
-       ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC);
-       if (ret)
-               return NULL;
-
-       rhashtable_walk_start(&iter);
+       int i = 0;
+       struct mesh_path *mpath;
 
-       while ((mpath = rhashtable_walk_next(&iter))) {
-               if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
-                       continue;
-               if (IS_ERR(mpath))
-                       break;
+       hlist_for_each_entry_rcu(mpath, &tbl->walk_head, walk_list) {
                if (i++ == idx)
                        break;
        }
-       rhashtable_walk_stop(&iter);
-       rhashtable_walk_exit(&iter);
 
-       if (IS_ERR(mpath) || !mpath)
+       if (!mpath)
                return NULL;
 
        if (mpath_expired(mpath)) {
@@ -432,6 +421,7 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
                return ERR_PTR(-ENOMEM);
 
        tbl = sdata->u.mesh.mesh_paths;
+       spin_lock_bh(&tbl->walk_lock);
        do {
                ret = rhashtable_lookup_insert_fast(&tbl->rhead,
                                                    &new_mpath->rhash,
@@ -441,20 +431,20 @@ struct mesh_path *mesh_path_add(struct ieee80211_sub_if_data *sdata,
                        mpath = rhashtable_lookup_fast(&tbl->rhead,
                                                       dst,
                                                       mesh_rht_params);
-
+               else if (!ret)
+                       hlist_add_head(&new_mpath->walk_list, &tbl->walk_head);
        } while (unlikely(ret == -EEXIST && !mpath));
+       spin_unlock_bh(&tbl->walk_lock);
 
-       if (ret && ret != -EEXIST)
-               return ERR_PTR(ret);
-
-       /* At this point either new_mpath was added, or we found a
-        * matching entry already in the table; in the latter case
-        * free the unnecessary new entry.
-        */
-       if (ret == -EEXIST) {
+       if (ret) {
                kfree(new_mpath);
+
+               if (ret != -EEXIST)
+                       return ERR_PTR(ret);
+
                new_mpath = mpath;
        }
+
        sdata->u.mesh.mesh_paths_generation++;
        return new_mpath;
 }
@@ -480,9 +470,17 @@ int mpp_path_add(struct ieee80211_sub_if_data *sdata,
 
        memcpy(new_mpath->mpp, mpp, ETH_ALEN);
        tbl = sdata->u.mesh.mpp_paths;
+
+       spin_lock_bh(&tbl->walk_lock);
        ret = rhashtable_lookup_insert_fast(&tbl->rhead,
                                            &new_mpath->rhash,
                                            mesh_rht_params);
+       if (!ret)
+               hlist_add_head_rcu(&new_mpath->walk_list, &tbl->walk_head);
+       spin_unlock_bh(&tbl->walk_lock);
+
+       if (ret)
+               kfree(new_mpath);
 
        sdata->u.mesh.mpp_paths_generation++;
        return ret;
@@ -503,20 +501,9 @@ void mesh_plink_broken(struct sta_info *sta)
        struct mesh_table *tbl = sdata->u.mesh.mesh_paths;
        static const u8 bcast[ETH_ALEN] = {0xff, 0xff, 0xff, 0xff, 0xff, 0xff};
        struct mesh_path *mpath;
-       struct rhashtable_iter iter;
-       int ret;
-
-       ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC);
-       if (ret)
-               return;
 
-       rhashtable_walk_start(&iter);
-
-       while ((mpath = rhashtable_walk_next(&iter))) {
-               if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
-                       continue;
-               if (IS_ERR(mpath))
-                       break;
+       rcu_read_lock();
+       hlist_for_each_entry_rcu(mpath, &tbl->walk_head, walk_list) {
                if (rcu_access_pointer(mpath->next_hop) == sta &&
                    mpath->flags & MESH_PATH_ACTIVE &&
                    !(mpath->flags & MESH_PATH_FIXED)) {
@@ -530,8 +517,7 @@ void mesh_plink_broken(struct sta_info *sta)
                                WLAN_REASON_MESH_PATH_DEST_UNREACHABLE, bcast);
                }
        }
-       rhashtable_walk_stop(&iter);
-       rhashtable_walk_exit(&iter);
+       rcu_read_unlock();
 }
 
 static void mesh_path_free_rcu(struct mesh_table *tbl,
@@ -551,6 +537,7 @@ static void mesh_path_free_rcu(struct mesh_table *tbl,
 
 static void __mesh_path_del(struct mesh_table *tbl, struct mesh_path *mpath)
 {
+       hlist_del_rcu(&mpath->walk_list);
        rhashtable_remove_fast(&tbl->rhead, &mpath->rhash, mesh_rht_params);
        mesh_path_free_rcu(tbl, mpath);
 }
@@ -571,27 +558,14 @@ void mesh_path_flush_by_nexthop(struct sta_info *sta)
        struct ieee80211_sub_if_data *sdata = sta->sdata;
        struct mesh_table *tbl = sdata->u.mesh.mesh_paths;
        struct mesh_path *mpath;
-       struct rhashtable_iter iter;
-       int ret;
-
-       ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC);
-       if (ret)
-               return;
-
-       rhashtable_walk_start(&iter);
-
-       while ((mpath = rhashtable_walk_next(&iter))) {
-               if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
-                       continue;
-               if (IS_ERR(mpath))
-                       break;
+       struct hlist_node *n;
 
+       spin_lock_bh(&tbl->walk_lock);
+       hlist_for_each_entry_safe(mpath, n, &tbl->walk_head, walk_list) {
                if (rcu_access_pointer(mpath->next_hop) == sta)
                        __mesh_path_del(tbl, mpath);
        }
-
-       rhashtable_walk_stop(&iter);
-       rhashtable_walk_exit(&iter);
+       spin_unlock_bh(&tbl->walk_lock);
 }
 
 static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata,
@@ -599,51 +573,26 @@ static void mpp_flush_by_proxy(struct ieee80211_sub_if_data *sdata,
 {
        struct mesh_table *tbl = sdata->u.mesh.mpp_paths;
        struct mesh_path *mpath;
-       struct rhashtable_iter iter;
-       int ret;
-
-       ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC);
-       if (ret)
-               return;
-
-       rhashtable_walk_start(&iter);
-
-       while ((mpath = rhashtable_walk_next(&iter))) {
-               if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
-                       continue;
-               if (IS_ERR(mpath))
-                       break;
+       struct hlist_node *n;
 
+       spin_lock_bh(&tbl->walk_lock);
+       hlist_for_each_entry_safe(mpath, n, &tbl->walk_head, walk_list) {
                if (ether_addr_equal(mpath->mpp, proxy))
                        __mesh_path_del(tbl, mpath);
        }
-
-       rhashtable_walk_stop(&iter);
-       rhashtable_walk_exit(&iter);
+       spin_unlock_bh(&tbl->walk_lock);
 }
 
 static void table_flush_by_iface(struct mesh_table *tbl)
 {
        struct mesh_path *mpath;
-       struct rhashtable_iter iter;
-       int ret;
-
-       ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_ATOMIC);
-       if (ret)
-               return;
-
-       rhashtable_walk_start(&iter);
+       struct hlist_node *n;
 
-       while ((mpath = rhashtable_walk_next(&iter))) {
-               if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
-                       continue;
-               if (IS_ERR(mpath))
-                       break;
+       spin_lock_bh(&tbl->walk_lock);
+       hlist_for_each_entry_safe(mpath, n, &tbl->walk_head, walk_list) {
                __mesh_path_del(tbl, mpath);
        }
-
-       rhashtable_walk_stop(&iter);
-       rhashtable_walk_exit(&iter);
+       spin_unlock_bh(&tbl->walk_lock);
 }
 
 /**
@@ -675,15 +624,15 @@ static int table_path_del(struct mesh_table *tbl,
 {
        struct mesh_path *mpath;
 
-       rcu_read_lock();
+       spin_lock_bh(&tbl->walk_lock);
        mpath = rhashtable_lookup_fast(&tbl->rhead, addr, mesh_rht_params);
        if (!mpath) {
-               rcu_read_unlock();
+               spin_unlock_bh(&tbl->walk_lock);
                return -ENXIO;
        }
 
        __mesh_path_del(tbl, mpath);
-       rcu_read_unlock();
+       spin_unlock_bh(&tbl->walk_lock);
        return 0;
 }
 
@@ -854,28 +803,16 @@ void mesh_path_tbl_expire(struct ieee80211_sub_if_data *sdata,
                          struct mesh_table *tbl)
 {
        struct mesh_path *mpath;
-       struct rhashtable_iter iter;
-       int ret;
+       struct hlist_node *n;
 
-       ret = rhashtable_walk_init(&tbl->rhead, &iter, GFP_KERNEL);
-       if (ret)
-               return;
-
-       rhashtable_walk_start(&iter);
-
-       while ((mpath = rhashtable_walk_next(&iter))) {
-               if (IS_ERR(mpath) && PTR_ERR(mpath) == -EAGAIN)
-                       continue;
-               if (IS_ERR(mpath))
-                       break;
+       spin_lock_bh(&tbl->walk_lock);
+       hlist_for_each_entry_safe(mpath, n, &tbl->walk_head, walk_list) {
                if ((!(mpath->flags & MESH_PATH_RESOLVING)) &&
                    (!(mpath->flags & MESH_PATH_FIXED)) &&
                     time_after(jiffies, mpath->exp_time + MESH_PATH_EXPIRE))
                        __mesh_path_del(tbl, mpath);
        }
-
-       rhashtable_walk_stop(&iter);
-       rhashtable_walk_exit(&iter);
+       spin_unlock_bh(&tbl->walk_lock);
 }
 
 void mesh_path_expire(struct ieee80211_sub_if_data *sdata)
index 45aad3d..c2a6da5 100644 (file)
@@ -231,7 +231,7 @@ static void ieee80211_handle_mu_mimo_mon(struct ieee80211_sub_if_data *sdata,
                struct ieee80211_hdr_3addr hdr;
                u8 category;
                u8 action_code;
-       } __packed action;
+       } __packed __aligned(2) action;
 
        if (!sdata)
                return;
@@ -2644,6 +2644,7 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        struct ieee80211_sub_if_data *sdata = rx->sdata;
        struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
        u16 ac, q, hdrlen;
+       int tailroom = 0;
 
        hdr = (struct ieee80211_hdr *) skb->data;
        hdrlen = ieee80211_hdrlen(hdr->frame_control);
@@ -2723,15 +2724,21 @@ ieee80211_rx_h_mesh_fwding(struct ieee80211_rx_data *rx)
        skb_set_queue_mapping(skb, q);
 
        if (!--mesh_hdr->ttl) {
-               IEEE80211_IFSTA_MESH_CTR_INC(ifmsh, dropped_frames_ttl);
+               if (!is_multicast_ether_addr(hdr->addr1))
+                       IEEE80211_IFSTA_MESH_CTR_INC(ifmsh,
+                                                    dropped_frames_ttl);
                goto out;
        }
 
        if (!ifmsh->mshcfg.dot11MeshForwarding)
                goto out;
 
+       if (sdata->crypto_tx_tailroom_needed_cnt)
+               tailroom = IEEE80211_ENCRYPT_TAILROOM;
+
        fwd_skb = skb_copy_expand(skb, local->tx_headroom +
-                                      sdata->encrypt_headroom, 0, GFP_ATOMIC);
+                                      sdata->encrypt_headroom,
+                                 tailroom, GFP_ATOMIC);
        if (!fwd_skb)
                goto out;
 
index f170d6c..928f13a 100644 (file)
@@ -1938,9 +1938,16 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
                                int head_need, bool may_encrypt)
 {
        struct ieee80211_local *local = sdata->local;
+       struct ieee80211_hdr *hdr;
+       bool enc_tailroom;
        int tail_need = 0;
 
-       if (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt) {
+       hdr = (struct ieee80211_hdr *) skb->data;
+       enc_tailroom = may_encrypt &&
+                      (sdata->crypto_tx_tailroom_needed_cnt ||
+                       ieee80211_is_mgmt(hdr->frame_control));
+
+       if (enc_tailroom) {
                tail_need = IEEE80211_ENCRYPT_TAILROOM;
                tail_need -= skb_tailroom(skb);
                tail_need = max_t(int, tail_need, 0);
@@ -1948,8 +1955,7 @@ static int ieee80211_skb_resize(struct ieee80211_sub_if_data *sdata,
 
        if (skb_cloned(skb) &&
            (!ieee80211_hw_check(&local->hw, SUPPORTS_CLONED_SKBS) ||
-            !skb_clone_writable(skb, ETH_HLEN) ||
-            (may_encrypt && sdata->crypto_tx_tailroom_needed_cnt)))
+            !skb_clone_writable(skb, ETH_HLEN) || enc_tailroom))
                I802_DEBUG_INC(local->tx_expand_skb_head_cloned);
        else if (head_need || tail_need)
                I802_DEBUG_INC(local->tx_expand_skb_head);
index d0eb38b..ba950ae 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2007      Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright (C) 2015-2017     Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018-2019 Intel Corporation
  *
  * This program is free software; you can redistribute it and/or modify
  * it under the terms of the GNU General Public License version 2 as
@@ -2146,6 +2146,10 @@ int ieee80211_reconfig(struct ieee80211_local *local)
                case NL80211_IFTYPE_AP_VLAN:
                case NL80211_IFTYPE_MONITOR:
                        break;
+               case NL80211_IFTYPE_ADHOC:
+                       if (sdata->vif.bss_conf.ibss_joined)
+                               WARN_ON(drv_join_ibss(local, sdata));
+                       /* fall through */
                default:
                        ieee80211_reconfig_stations(sdata);
                        /* fall through */
index cad48d0..8401cef 100644 (file)
@@ -29,6 +29,7 @@ config        IP_VS_IPV6
        bool "IPv6 support for IPVS"
        depends on IPV6 = y || IP_VS = IPV6
        select IP6_NF_IPTABLES
+       select NF_DEFRAG_IPV6
        ---help---
          Add IPv6 support to IPVS.
 
index fe9abf3..235205c 100644 (file)
@@ -1536,14 +1536,12 @@ ip_vs_try_to_schedule(struct netns_ipvs *ipvs, int af, struct sk_buff *skb,
                /* sorry, all this trouble for a no-hit :) */
                IP_VS_DBG_PKT(12, af, pp, skb, iph->off,
                              "ip_vs_in: packet continues traversal as normal");
-               if (iph->fragoffs) {
-                       /* Fragment that couldn't be mapped to a conn entry
-                        * is missing module nf_defrag_ipv6
-                        */
-                       IP_VS_DBG_RL("Unhandled frag, load nf_defrag_ipv6\n");
+
+               /* Fragment couldn't be mapped to a conn entry */
+               if (iph->fragoffs)
                        IP_VS_DBG_PKT(7, af, pp, skb, iph->off,
                                      "unhandled fragment");
-               }
+
                *verdict = NF_ACCEPT;
                return 0;
        }
index 432141f..ac8d848 100644 (file)
@@ -43,6 +43,7 @@
 #ifdef CONFIG_IP_VS_IPV6
 #include <net/ipv6.h>
 #include <net/ip6_route.h>
+#include <net/netfilter/ipv6/nf_defrag_ipv6.h>
 #endif
 #include <net/route.h>
 #include <net/sock.h>
@@ -900,11 +901,17 @@ ip_vs_new_dest(struct ip_vs_service *svc, struct ip_vs_dest_user_kern *udest,
 
 #ifdef CONFIG_IP_VS_IPV6
        if (udest->af == AF_INET6) {
+               int ret;
+
                atype = ipv6_addr_type(&udest->addr.in6);
                if ((!(atype & IPV6_ADDR_UNICAST) ||
                        atype & IPV6_ADDR_LINKLOCAL) &&
                        !__ip_vs_addr_is_local_v6(svc->ipvs->net, &udest->addr.in6))
                        return -EINVAL;
+
+               ret = nf_defrag_ipv6_enable(svc->ipvs->net);
+               if (ret)
+                       return ret;
        } else
 #endif
        {
@@ -1228,6 +1235,10 @@ ip_vs_add_service(struct netns_ipvs *ipvs, struct ip_vs_service_user_kern *u,
                        ret = -EINVAL;
                        goto out_err;
                }
+
+               ret = nf_defrag_ipv6_enable(ipvs->net);
+               if (ret)
+                       goto out_err;
        }
 #endif
 
@@ -2220,6 +2231,18 @@ static int ip_vs_set_timeout(struct netns_ipvs *ipvs, struct ip_vs_timeout_user
                  u->tcp_fin_timeout,
                  u->udp_timeout);
 
+#ifdef CONFIG_IP_VS_PROTO_TCP
+       if (u->tcp_timeout < 0 || u->tcp_timeout > (INT_MAX / HZ) ||
+           u->tcp_fin_timeout < 0 || u->tcp_fin_timeout > (INT_MAX / HZ)) {
+               return -EINVAL;
+       }
+#endif
+
+#ifdef CONFIG_IP_VS_PROTO_UDP
+       if (u->udp_timeout < 0 || u->udp_timeout > (INT_MAX / HZ))
+               return -EINVAL;
+#endif
+
 #ifdef CONFIG_IP_VS_PROTO_TCP
        if (u->tcp_timeout) {
                pd = ip_vs_proto_data_get(ipvs, IPPROTO_TCP);
index 741b533..db4d463 100644 (file)
@@ -1007,6 +1007,22 @@ nf_conntrack_tuple_taken(const struct nf_conntrack_tuple *tuple,
                }
 
                if (nf_ct_key_equal(h, tuple, zone, net)) {
+                       /* Tuple is taken already, so caller will need to find
+                        * a new source port to use.
+                        *
+                        * Only exception:
+                        * If the *original tuples* are identical, then both
+                        * conntracks refer to the same flow.
+                        * This is a rare situation, it can occur e.g. when
+                        * more than one UDP packet is sent from same socket
+                        * in different threads.
+                        *
+                        * Let nf_ct_resolve_clash() deal with this later.
+                        */
+                       if (nf_ct_tuple_equal(&ignored_conntrack->tuplehash[IP_CT_DIR_ORIGINAL].tuple,
+                                             &ct->tuplehash[IP_CT_DIR_ORIGINAL].tuple))
+                               continue;
+
                        NF_CT_STAT_INC_ATOMIC(net, found);
                        rcu_read_unlock();
                        return 1;
index fa0844e..c0c72ae 100644 (file)
@@ -28,6 +28,7 @@ flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct,
 {
        struct flow_offload_tuple *ft = &flow->tuplehash[dir].tuple;
        struct nf_conntrack_tuple *ctt = &ct->tuplehash[dir].tuple;
+       struct dst_entry *other_dst = route->tuple[!dir].dst;
        struct dst_entry *dst = route->tuple[dir].dst;
 
        ft->dir = dir;
@@ -50,8 +51,8 @@ flow_offload_fill_dir(struct flow_offload *flow, struct nf_conn *ct,
        ft->src_port = ctt->src.u.tcp.port;
        ft->dst_port = ctt->dst.u.tcp.port;
 
-       ft->iifidx = route->tuple[dir].ifindex;
-       ft->oifidx = route->tuple[!dir].ifindex;
+       ft->iifidx = other_dst->dev->ifindex;
+       ft->oifidx = dst->dev->ifindex;
        ft->dst_cache = dst;
 }
 
index 2b0a933..4893f24 100644 (file)
@@ -116,6 +116,23 @@ static void nft_trans_destroy(struct nft_trans *trans)
        kfree(trans);
 }
 
+static void nft_set_trans_bind(const struct nft_ctx *ctx, struct nft_set *set)
+{
+       struct net *net = ctx->net;
+       struct nft_trans *trans;
+
+       if (!nft_set_is_anonymous(set))
+               return;
+
+       list_for_each_entry_reverse(trans, &net->nft.commit_list, list) {
+               if (trans->msg_type == NFT_MSG_NEWSET &&
+                   nft_trans_set(trans) == set) {
+                       nft_trans_set_bound(trans) = true;
+                       break;
+               }
+       }
+}
+
 static int nf_tables_register_hook(struct net *net,
                                   const struct nft_table *table,
                                   struct nft_chain *chain)
@@ -211,18 +228,6 @@ static int nft_delchain(struct nft_ctx *ctx)
        return err;
 }
 
-/* either expr ops provide both activate/deactivate, or neither */
-static bool nft_expr_check_ops(const struct nft_expr_ops *ops)
-{
-       if (!ops)
-               return true;
-
-       if (WARN_ON_ONCE((!ops->activate ^ !ops->deactivate)))
-               return false;
-
-       return true;
-}
-
 static void nft_rule_expr_activate(const struct nft_ctx *ctx,
                                   struct nft_rule *rule)
 {
@@ -238,14 +243,15 @@ static void nft_rule_expr_activate(const struct nft_ctx *ctx,
 }
 
 static void nft_rule_expr_deactivate(const struct nft_ctx *ctx,
-                                    struct nft_rule *rule)
+                                    struct nft_rule *rule,
+                                    enum nft_trans_phase phase)
 {
        struct nft_expr *expr;
 
        expr = nft_expr_first(rule);
        while (expr != nft_expr_last(rule) && expr->ops) {
                if (expr->ops->deactivate)
-                       expr->ops->deactivate(ctx, expr);
+                       expr->ops->deactivate(ctx, expr, phase);
 
                expr = nft_expr_next(expr);
        }
@@ -296,7 +302,7 @@ static int nft_delrule(struct nft_ctx *ctx, struct nft_rule *rule)
                nft_trans_destroy(trans);
                return err;
        }
-       nft_rule_expr_deactivate(ctx, rule);
+       nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_PREPARE);
 
        return 0;
 }
@@ -307,6 +313,9 @@ static int nft_delrule_by_chain(struct nft_ctx *ctx)
        int err;
 
        list_for_each_entry(rule, &ctx->chain->rules, list) {
+               if (!nft_is_active_next(ctx->net, rule))
+                       continue;
+
                err = nft_delrule(ctx, rule);
                if (err < 0)
                        return err;
@@ -1929,9 +1938,6 @@ static int nf_tables_delchain(struct net *net, struct sock *nlsk,
  */
 int nft_register_expr(struct nft_expr_type *type)
 {
-       if (!nft_expr_check_ops(type->ops))
-               return -EINVAL;
-
        nfnl_lock(NFNL_SUBSYS_NFTABLES);
        if (type->family == NFPROTO_UNSPEC)
                list_add_tail_rcu(&type->list, &nf_tables_expressions);
@@ -2079,10 +2085,6 @@ static int nf_tables_expr_parse(const struct nft_ctx *ctx,
                        err = PTR_ERR(ops);
                        goto err1;
                }
-               if (!nft_expr_check_ops(ops)) {
-                       err = -EINVAL;
-                       goto err1;
-               }
        } else
                ops = type->ops;
 
@@ -2304,7 +2306,6 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
        struct net *net = sock_net(skb->sk);
        unsigned int s_idx = cb->args[0];
        const struct nft_rule *rule;
-       int rc = 1;
 
        list_for_each_entry_rcu(rule, &chain->rules, list) {
                if (!nft_is_active(net, rule))
@@ -2321,16 +2322,13 @@ static int __nf_tables_dump_rules(struct sk_buff *skb,
                                        NLM_F_MULTI | NLM_F_APPEND,
                                        table->family,
                                        table, chain, rule) < 0)
-                       goto out_unfinished;
+                       return 1;
 
                nl_dump_check_consistent(cb, nlmsg_hdr(skb));
 cont:
                (*idx)++;
        }
-       rc = 0;
-out_unfinished:
-       cb->args[0] = *idx;
-       return rc;
+       return 0;
 }
 
 static int nf_tables_dump_rules(struct sk_buff *skb,
@@ -2354,7 +2352,7 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
                if (ctx && ctx->table && strcmp(ctx->table, table->name) != 0)
                        continue;
 
-               if (ctx && ctx->chain) {
+               if (ctx && ctx->table && ctx->chain) {
                        struct rhlist_head *list, *tmp;
 
                        list = rhltable_lookup(&table->chains_ht, ctx->chain,
@@ -2382,6 +2380,8 @@ static int nf_tables_dump_rules(struct sk_buff *skb,
        }
 done:
        rcu_read_unlock();
+
+       cb->args[0] = idx;
        return skb->len;
 }
 
@@ -2513,7 +2513,7 @@ static void nf_tables_rule_destroy(const struct nft_ctx *ctx,
 static void nf_tables_rule_release(const struct nft_ctx *ctx,
                                   struct nft_rule *rule)
 {
-       nft_rule_expr_deactivate(ctx, rule);
+       nft_rule_expr_deactivate(ctx, rule, NFT_TRANS_RELEASE);
        nf_tables_rule_destroy(ctx, rule);
 }
 
@@ -3710,39 +3710,30 @@ int nf_tables_bind_set(const struct nft_ctx *ctx, struct nft_set *set,
 bind:
        binding->chain = ctx->chain;
        list_add_tail_rcu(&binding->list, &set->bindings);
+       nft_set_trans_bind(ctx, set);
+
        return 0;
 }
 EXPORT_SYMBOL_GPL(nf_tables_bind_set);
 
-void nf_tables_rebind_set(const struct nft_ctx *ctx, struct nft_set *set,
-                         struct nft_set_binding *binding)
-{
-       if (list_empty(&set->bindings) && nft_set_is_anonymous(set) &&
-           nft_is_active(ctx->net, set))
-               list_add_tail_rcu(&set->list, &ctx->table->sets);
-
-       list_add_tail_rcu(&binding->list, &set->bindings);
-}
-EXPORT_SYMBOL_GPL(nf_tables_rebind_set);
-
 void nf_tables_unbind_set(const struct nft_ctx *ctx, struct nft_set *set,
-                         struct nft_set_binding *binding)
+                         struct nft_set_binding *binding, bool event)
 {
        list_del_rcu(&binding->list);
 
-       if (list_empty(&set->bindings) && nft_set_is_anonymous(set) &&
-           nft_is_active(ctx->net, set))
+       if (list_empty(&set->bindings) && nft_set_is_anonymous(set)) {
                list_del_rcu(&set->list);
+               if (event)
+                       nf_tables_set_notify(ctx, set, NFT_MSG_DELSET,
+                                            GFP_KERNEL);
+       }
 }
 EXPORT_SYMBOL_GPL(nf_tables_unbind_set);
 
 void nf_tables_destroy_set(const struct nft_ctx *ctx, struct nft_set *set)
 {
-       if (list_empty(&set->bindings) && nft_set_is_anonymous(set) &&
-           nft_is_active(ctx->net, set)) {
-               nf_tables_set_notify(ctx, set, NFT_MSG_DELSET, GFP_ATOMIC);
+       if (list_empty(&set->bindings) && nft_set_is_anonymous(set))
                nft_set_destroy(set);
-       }
 }
 EXPORT_SYMBOL_GPL(nf_tables_destroy_set);
 
@@ -4508,6 +4499,8 @@ err6:
 err5:
        kfree(trans);
 err4:
+       if (obj)
+               obj->use--;
        kfree(elem.priv);
 err3:
        if (nla[NFTA_SET_ELEM_DATA] != NULL)
@@ -6535,6 +6528,9 @@ static int nf_tables_commit(struct net *net, struct sk_buff *skb)
                        nf_tables_rule_notify(&trans->ctx,
                                              nft_trans_rule(trans),
                                              NFT_MSG_DELRULE);
+                       nft_rule_expr_deactivate(&trans->ctx,
+                                                nft_trans_rule(trans),
+                                                NFT_TRANS_COMMIT);
                        break;
                case NFT_MSG_NEWSET:
                        nft_clear(net, nft_trans_set(trans));
@@ -6621,7 +6617,8 @@ static void nf_tables_abort_release(struct nft_trans *trans)
                nf_tables_rule_destroy(&trans->ctx, nft_trans_rule(trans));
                break;
        case NFT_MSG_NEWSET:
-               nft_set_destroy(nft_trans_set(trans));
+               if (!nft_trans_set_bound(trans))
+                       nft_set_destroy(nft_trans_set(trans));
                break;
        case NFT_MSG_NEWSETELEM:
                nft_set_elem_destroy(nft_trans_elem_set(trans),
@@ -6682,7 +6679,9 @@ static int __nf_tables_abort(struct net *net)
                case NFT_MSG_NEWRULE:
                        trans->ctx.chain->use--;
                        list_del_rcu(&nft_trans_rule(trans)->list);
-                       nft_rule_expr_deactivate(&trans->ctx, nft_trans_rule(trans));
+                       nft_rule_expr_deactivate(&trans->ctx,
+                                                nft_trans_rule(trans),
+                                                NFT_TRANS_ABORT);
                        break;
                case NFT_MSG_DELRULE:
                        trans->ctx.chain->use++;
@@ -6692,7 +6691,8 @@ static int __nf_tables_abort(struct net *net)
                        break;
                case NFT_MSG_NEWSET:
                        trans->ctx.table->use--;
-                       list_del_rcu(&nft_trans_set(trans)->list);
+                       if (!nft_trans_set_bound(trans))
+                               list_del_rcu(&nft_trans_set(trans)->list);
                        break;
                case NFT_MSG_DELSET:
                        trans->ctx.table->use++;
index 6f41dd7..1f1d90c 100644 (file)
@@ -66,6 +66,7 @@ static bool nf_osf_match_one(const struct sk_buff *skb,
                             int ttl_check,
                             struct nf_osf_hdr_ctx *ctx)
 {
+       const __u8 *optpinit = ctx->optp;
        unsigned int check_WSS = 0;
        int fmatch = FMATCH_WRONG;
        int foptsize, optnum;
@@ -155,6 +156,9 @@ static bool nf_osf_match_one(const struct sk_buff *skb,
                }
        }
 
+       if (fmatch != FMATCH_OK)
+               ctx->optp = optpinit;
+
        return fmatch == FMATCH_OK;
 }
 
index 7334e0b..0a4bad5 100644 (file)
 #include <linux/netfilter_bridge/ebtables.h>
 #include <linux/netfilter_arp/arp_tables.h>
 #include <net/netfilter/nf_tables.h>
+#include <net/netns/generic.h>
 
 struct nft_xt {
        struct list_head        head;
        struct nft_expr_ops     ops;
-       unsigned int            refcnt;
+       refcount_t              refcnt;
+
+       /* used only when transaction mutex is locked */
+       unsigned int            listcnt;
 
        /* Unlike other expressions, ops doesn't have static storage duration.
         * nft core assumes they do.  We use kfree_rcu so that nft core can
@@ -43,10 +47,39 @@ struct nft_xt_match_priv {
        void *info;
 };
 
+struct nft_compat_net {
+       struct list_head nft_target_list;
+       struct list_head nft_match_list;
+};
+
+static unsigned int nft_compat_net_id __read_mostly;
+static struct nft_expr_type nft_match_type;
+static struct nft_expr_type nft_target_type;
+
+static struct nft_compat_net *nft_compat_pernet(struct net *net)
+{
+       return net_generic(net, nft_compat_net_id);
+}
+
+static void nft_xt_get(struct nft_xt *xt)
+{
+       /* refcount_inc() warns on 0 -> 1 transition, but we can't
+        * init the reference count to 1 in .select_ops -- we can't
+        * undo such an increase when another expression inside the same
+        * rule fails afterwards.
+        */
+       if (xt->listcnt == 0)
+               refcount_set(&xt->refcnt, 1);
+       else
+               refcount_inc(&xt->refcnt);
+
+       xt->listcnt++;
+}
+
 static bool nft_xt_put(struct nft_xt *xt)
 {
-       if (--xt->refcnt == 0) {
-               list_del(&xt->head);
+       if (refcount_dec_and_test(&xt->refcnt)) {
+               WARN_ON_ONCE(!list_empty(&xt->head));
                kfree_rcu(xt, rcu_head);
                return true;
        }
@@ -273,7 +306,7 @@ nft_target_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
                return -EINVAL;
 
        nft_xt = container_of(expr->ops, struct nft_xt, ops);
-       nft_xt->refcnt++;
+       nft_xt_get(nft_xt);
        return 0;
 }
 
@@ -282,6 +315,7 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 {
        struct xt_target *target = expr->ops->data;
        void *info = nft_expr_priv(expr);
+       struct module *me = target->me;
        struct xt_tgdtor_param par;
 
        par.net = ctx->net;
@@ -292,7 +326,7 @@ nft_target_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
                par.target->destroy(&par);
 
        if (nft_xt_put(container_of(expr->ops, struct nft_xt, ops)))
-               module_put(target->me);
+               module_put(me);
 }
 
 static int nft_extension_dump_info(struct sk_buff *skb, int attr,
@@ -486,7 +520,7 @@ __nft_match_init(const struct nft_ctx *ctx, const struct nft_expr *expr,
                return ret;
 
        nft_xt = container_of(expr->ops, struct nft_xt, ops);
-       nft_xt->refcnt++;
+       nft_xt_get(nft_xt);
        return 0;
 }
 
@@ -540,6 +574,18 @@ nft_match_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
        __nft_match_destroy(ctx, expr, nft_expr_priv(expr));
 }
 
+static void nft_compat_deactivate(const struct nft_ctx *ctx,
+                                 const struct nft_expr *expr,
+                                 enum nft_trans_phase phase)
+{
+       struct nft_xt *xt = container_of(expr->ops, struct nft_xt, ops);
+
+       if (phase == NFT_TRANS_ABORT || phase == NFT_TRANS_COMMIT) {
+               if (--xt->listcnt == 0)
+                       list_del_init(&xt->head);
+       }
+}
+
 static void
 nft_match_large_destroy(const struct nft_ctx *ctx, const struct nft_expr *expr)
 {
@@ -734,10 +780,6 @@ static const struct nfnetlink_subsystem nfnl_compat_subsys = {
        .cb             = nfnl_nft_compat_cb,
 };
 
-static LIST_HEAD(nft_match_list);
-
-static struct nft_expr_type nft_match_type;
-
 static bool nft_match_cmp(const struct xt_match *match,
                          const char *name, u32 rev, u32 family)
 {
@@ -749,6 +791,7 @@ static const struct nft_expr_ops *
 nft_match_select_ops(const struct nft_ctx *ctx,
                     const struct nlattr * const tb[])
 {
+       struct nft_compat_net *cn;
        struct nft_xt *nft_match;
        struct xt_match *match;
        unsigned int matchsize;
@@ -765,8 +808,10 @@ nft_match_select_ops(const struct nft_ctx *ctx,
        rev = ntohl(nla_get_be32(tb[NFTA_MATCH_REV]));
        family = ctx->family;
 
+       cn = nft_compat_pernet(ctx->net);
+
        /* Re-use the existing match if it's already loaded. */
-       list_for_each_entry(nft_match, &nft_match_list, head) {
+       list_for_each_entry(nft_match, &cn->nft_match_list, head) {
                struct xt_match *match = nft_match->ops.data;
 
                if (nft_match_cmp(match, mt_name, rev, family))
@@ -789,11 +834,12 @@ nft_match_select_ops(const struct nft_ctx *ctx,
                goto err;
        }
 
-       nft_match->refcnt = 0;
+       refcount_set(&nft_match->refcnt, 0);
        nft_match->ops.type = &nft_match_type;
        nft_match->ops.eval = nft_match_eval;
        nft_match->ops.init = nft_match_init;
        nft_match->ops.destroy = nft_match_destroy;
+       nft_match->ops.deactivate = nft_compat_deactivate;
        nft_match->ops.dump = nft_match_dump;
        nft_match->ops.validate = nft_match_validate;
        nft_match->ops.data = match;
@@ -810,7 +856,8 @@ nft_match_select_ops(const struct nft_ctx *ctx,
 
        nft_match->ops.size = matchsize;
 
-       list_add(&nft_match->head, &nft_match_list);
+       nft_match->listcnt = 0;
+       list_add(&nft_match->head, &cn->nft_match_list);
 
        return &nft_match->ops;
 err:
@@ -826,10 +873,6 @@ static struct nft_expr_type nft_match_type __read_mostly = {
        .owner          = THIS_MODULE,
 };
 
-static LIST_HEAD(nft_target_list);
-
-static struct nft_expr_type nft_target_type;
-
 static bool nft_target_cmp(const struct xt_target *tg,
                           const char *name, u32 rev, u32 family)
 {
@@ -841,6 +884,7 @@ static const struct nft_expr_ops *
 nft_target_select_ops(const struct nft_ctx *ctx,
                      const struct nlattr * const tb[])
 {
+       struct nft_compat_net *cn;
        struct nft_xt *nft_target;
        struct xt_target *target;
        char *tg_name;
@@ -861,8 +905,9 @@ nft_target_select_ops(const struct nft_ctx *ctx,
            strcmp(tg_name, "standard") == 0)
                return ERR_PTR(-EINVAL);
 
+       cn = nft_compat_pernet(ctx->net);
        /* Re-use the existing target if it's already loaded. */
-       list_for_each_entry(nft_target, &nft_target_list, head) {
+       list_for_each_entry(nft_target, &cn->nft_target_list, head) {
                struct xt_target *target = nft_target->ops.data;
 
                if (!target->target)
@@ -893,11 +938,12 @@ nft_target_select_ops(const struct nft_ctx *ctx,
                goto err;
        }
 
-       nft_target->refcnt = 0;
+       refcount_set(&nft_target->refcnt, 0);
        nft_target->ops.type = &nft_target_type;
        nft_target->ops.size = NFT_EXPR_SIZE(XT_ALIGN(target->targetsize));
        nft_target->ops.init = nft_target_init;
        nft_target->ops.destroy = nft_target_destroy;
+       nft_target->ops.deactivate = nft_compat_deactivate;
        nft_target->ops.dump = nft_target_dump;
        nft_target->ops.validate = nft_target_validate;
        nft_target->ops.data = target;
@@ -907,7 +953,8 @@ nft_target_select_ops(const struct nft_ctx *ctx,
        else
                nft_target->ops.eval = nft_target_eval_xt;
 
-       list_add(&nft_target->head, &nft_target_list);
+       nft_target->listcnt = 0;
+       list_add(&nft_target->head, &cn->nft_target_list);
 
        return &nft_target->ops;
 err:
@@ -923,13 +970,74 @@ static struct nft_expr_type nft_target_type __read_mostly = {
        .owner          = THIS_MODULE,
 };
 
+static int __net_init nft_compat_init_net(struct net *net)
+{
+       struct nft_compat_net *cn = nft_compat_pernet(net);
+
+       INIT_LIST_HEAD(&cn->nft_target_list);
+       INIT_LIST_HEAD(&cn->nft_match_list);
+
+       return 0;
+}
+
+static void __net_exit nft_compat_exit_net(struct net *net)
+{
+       struct nft_compat_net *cn = nft_compat_pernet(net);
+       struct nft_xt *xt, *next;
+
+       if (list_empty(&cn->nft_match_list) &&
+           list_empty(&cn->nft_target_list))
+               return;
+
+       /* If there was an error that caused nft_xt expr to not be initialized
+        * fully and noone else requested the same expression later, the lists
+        * contain 0-refcount entries that still hold module reference.
+        *
+        * Clean them here.
+        */
+       mutex_lock(&net->nft.commit_mutex);
+       list_for_each_entry_safe(xt, next, &cn->nft_target_list, head) {
+               struct xt_target *target = xt->ops.data;
+
+               list_del_init(&xt->head);
+
+               if (refcount_read(&xt->refcnt))
+                       continue;
+               module_put(target->me);
+               kfree(xt);
+       }
+
+       list_for_each_entry_safe(xt, next, &cn->nft_match_list, head) {
+               struct xt_match *match = xt->ops.data;
+
+               list_del_init(&xt->head);
+
+               if (refcount_read(&xt->refcnt))
+                       continue;
+               module_put(match->me);
+               kfree(xt);
+       }
+       mutex_unlock(&net->nft.commit_mutex);
+}
+
+static struct pernet_operations nft_compat_net_ops = {
+       .init   = nft_compat_init_net,
+       .exit   = nft_compat_exit_net,
+       .id     = &nft_compat_net_id,
+       .size   = sizeof(struct nft_compat_net),
+};
+
 static int __init nft_compat_module_init(void)
 {
        int ret;
 
+       ret = register_pernet_subsys(&nft_compat_net_ops);
+       if (ret < 0)
+               goto err_target;
+
        ret = nft_register_expr(&nft_match_type);
        if (ret < 0)
-               return ret;
+               goto err_pernet;
 
        ret = nft_register_expr(&nft_target_type);
        if (ret < 0)
@@ -942,45 +1050,21 @@ static int __init nft_compat_module_init(void)
        }
 
        return ret;
-
 err_target:
        nft_unregister_expr(&nft_target_type);
 err_match:
        nft_unregister_expr(&nft_match_type);
+err_pernet:
+       unregister_pernet_subsys(&nft_compat_net_ops);
        return ret;
 }
 
 static void __exit nft_compat_module_exit(void)
 {
-       struct nft_xt *xt, *next;
-
-       /* list should be empty here, it can be non-empty only in case there
-        * was an error that caused nft_xt expr to not be initialized fully
-        * and noone else requested the same expression later.
-        *
-        * In this case, the lists contain 0-refcount entries that still
-        * hold module reference.
-        */
-       list_for_each_entry_safe(xt, next, &nft_target_list, head) {
-               struct xt_target *target = xt->ops.data;
-
-               if (WARN_ON_ONCE(xt->refcnt))
-                       continue;
-               module_put(target->me);
-               kfree(xt);
-       }
-
-       list_for_each_entry_safe(xt, next, &nft_match_list, head) {
-               struct xt_match *match = xt->ops.data;
-
-               if (WARN_ON_ONCE(xt->refcnt))
-                       continue;
-               module_put(match->me);
-               kfree(xt);
-       }
        nfnetlink_subsys_unregister(&nfnl_compat_subsys);
        nft_unregister_expr(&nft_target_type);
        nft_unregister_expr(&nft_match_type);
+       unregister_pernet_subsys(&nft_compat_net_ops);
 }
 
 MODULE_ALIAS_NFNL_SUBSYS(NFNL_SUBSYS_NFT_COMPAT);
index 07d4efd..f1172f9 100644 (file)
@@ -235,20 +235,17 @@ err1:
        return err;
 }
 
-static void nft_dynset_activate(const struct nft_ctx *ctx,
-                               const struct nft_expr *expr)
-{
-       struct nft_dynset *priv = nft_expr_priv(expr);
-
-       nf_tables_rebind_set(ctx, priv->set, &priv->binding);
-}
-
 static void nft_dynset_deactivate(const struct nft_ctx *ctx,
-                                 const struct nft_expr *expr)
+                                 const struct nft_expr *expr,
+                                 enum nft_trans_phase phase)
 {
        struct nft_dynset *priv = nft_expr_priv(expr);
 
-       nf_tables_unbind_set(ctx, priv->set, &priv->binding);
+       if (phase == NFT_TRANS_PREPARE)
+               return;
+
+       nf_tables_unbind_set(ctx, priv->set, &priv->binding,
+                            phase == NFT_TRANS_COMMIT);
 }
 
 static void nft_dynset_destroy(const struct nft_ctx *ctx,
@@ -296,7 +293,6 @@ static const struct nft_expr_ops nft_dynset_ops = {
        .eval           = nft_dynset_eval,
        .init           = nft_dynset_init,
        .destroy        = nft_dynset_destroy,
-       .activate       = nft_dynset_activate,
        .deactivate     = nft_dynset_deactivate,
        .dump           = nft_dynset_dump,
 };
index 974525e..6e6b9ad 100644 (file)
@@ -12,6 +12,7 @@
 #include <net/netfilter/nf_conntrack_core.h>
 #include <linux/netfilter/nf_conntrack_common.h>
 #include <net/netfilter/nf_flow_table.h>
+#include <net/netfilter/nf_conntrack_helper.h>
 
 struct nft_flow_offload {
        struct nft_flowtable    *flowtable;
@@ -29,10 +30,12 @@ static int nft_flow_route(const struct nft_pktinfo *pkt,
        memset(&fl, 0, sizeof(fl));
        switch (nft_pf(pkt)) {
        case NFPROTO_IPV4:
-               fl.u.ip4.daddr = ct->tuplehash[!dir].tuple.dst.u3.ip;
+               fl.u.ip4.daddr = ct->tuplehash[dir].tuple.src.u3.ip;
+               fl.u.ip4.flowi4_oif = nft_in(pkt)->ifindex;
                break;
        case NFPROTO_IPV6:
-               fl.u.ip6.daddr = ct->tuplehash[!dir].tuple.dst.u3.in6;
+               fl.u.ip6.daddr = ct->tuplehash[dir].tuple.src.u3.in6;
+               fl.u.ip6.flowi6_oif = nft_in(pkt)->ifindex;
                break;
        }
 
@@ -41,9 +44,7 @@ static int nft_flow_route(const struct nft_pktinfo *pkt,
                return -ENOENT;
 
        route->tuple[dir].dst           = this_dst;
-       route->tuple[dir].ifindex       = nft_in(pkt)->ifindex;
        route->tuple[!dir].dst          = other_dst;
-       route->tuple[!dir].ifindex      = nft_out(pkt)->ifindex;
 
        return 0;
 }
@@ -66,6 +67,7 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
 {
        struct nft_flow_offload *priv = nft_expr_priv(expr);
        struct nf_flowtable *flowtable = &priv->flowtable->data;
+       const struct nf_conn_help *help;
        enum ip_conntrack_info ctinfo;
        struct nf_flow_route route;
        struct flow_offload *flow;
@@ -88,7 +90,8 @@ static void nft_flow_offload_eval(const struct nft_expr *expr,
                goto out;
        }
 
-       if (test_bit(IPS_HELPER_BIT, &ct->status))
+       help = nfct_help(ct);
+       if (help)
                goto out;
 
        if (ctinfo == IP_CT_NEW ||
index 0777a93..3f6d1d2 100644 (file)
@@ -72,10 +72,14 @@ static void nft_immediate_activate(const struct nft_ctx *ctx,
 }
 
 static void nft_immediate_deactivate(const struct nft_ctx *ctx,
-                                    const struct nft_expr *expr)
+                                    const struct nft_expr *expr,
+                                    enum nft_trans_phase phase)
 {
        const struct nft_immediate_expr *priv = nft_expr_priv(expr);
 
+       if (phase == NFT_TRANS_COMMIT)
+               return;
+
        return nft_data_release(&priv->data, nft_dreg_to_type(priv->dreg));
 }
 
index 227b2b1..14496da 100644 (file)
@@ -121,20 +121,17 @@ static int nft_lookup_init(const struct nft_ctx *ctx,
        return 0;
 }
 
-static void nft_lookup_activate(const struct nft_ctx *ctx,
-                               const struct nft_expr *expr)
-{
-       struct nft_lookup *priv = nft_expr_priv(expr);
-
-       nf_tables_rebind_set(ctx, priv->set, &priv->binding);
-}
-
 static void nft_lookup_deactivate(const struct nft_ctx *ctx,
-                                 const struct nft_expr *expr)
+                                 const struct nft_expr *expr,
+                                 enum nft_trans_phase phase)
 {
        struct nft_lookup *priv = nft_expr_priv(expr);
 
-       nf_tables_unbind_set(ctx, priv->set, &priv->binding);
+       if (phase == NFT_TRANS_PREPARE)
+               return;
+
+       nf_tables_unbind_set(ctx, priv->set, &priv->binding,
+                            phase == NFT_TRANS_COMMIT);
 }
 
 static void nft_lookup_destroy(const struct nft_ctx *ctx,
@@ -225,7 +222,6 @@ static const struct nft_expr_ops nft_lookup_ops = {
        .size           = NFT_EXPR_SIZE(sizeof(struct nft_lookup)),
        .eval           = nft_lookup_eval,
        .init           = nft_lookup_init,
-       .activate       = nft_lookup_activate,
        .deactivate     = nft_lookup_deactivate,
        .destroy        = nft_lookup_destroy,
        .dump           = nft_lookup_dump,
index a3185ca..ae178e9 100644 (file)
@@ -155,20 +155,17 @@ nla_put_failure:
        return -1;
 }
 
-static void nft_objref_map_activate(const struct nft_ctx *ctx,
-                                   const struct nft_expr *expr)
-{
-       struct nft_objref_map *priv = nft_expr_priv(expr);
-
-       nf_tables_rebind_set(ctx, priv->set, &priv->binding);
-}
-
 static void nft_objref_map_deactivate(const struct nft_ctx *ctx,
-                                     const struct nft_expr *expr)
+                                     const struct nft_expr *expr,
+                                     enum nft_trans_phase phase)
 {
        struct nft_objref_map *priv = nft_expr_priv(expr);
 
-       nf_tables_unbind_set(ctx, priv->set, &priv->binding);
+       if (phase == NFT_TRANS_PREPARE)
+               return;
+
+       nf_tables_unbind_set(ctx, priv->set, &priv->binding,
+                            phase == NFT_TRANS_COMMIT);
 }
 
 static void nft_objref_map_destroy(const struct nft_ctx *ctx,
@@ -185,7 +182,6 @@ static const struct nft_expr_ops nft_objref_map_ops = {
        .size           = NFT_EXPR_SIZE(sizeof(struct nft_objref_map)),
        .eval           = nft_objref_map_eval,
        .init           = nft_objref_map_init,
-       .activate       = nft_objref_map_activate,
        .deactivate     = nft_objref_map_deactivate,
        .destroy        = nft_objref_map_destroy,
        .dump           = nft_objref_map_dump,
index aecadd4..13e1ac3 100644 (file)
@@ -1899,7 +1899,7 @@ static int __init xt_init(void)
                seqcount_init(&per_cpu(xt_recseq, i));
        }
 
-       xt = kmalloc_array(NFPROTO_NUMPROTO, sizeof(struct xt_af), GFP_KERNEL);
+       xt = kcalloc(NFPROTO_NUMPROTO, sizeof(struct xt_af), GFP_KERNEL);
        if (!xt)
                return -ENOMEM;
 
index cbd51ed..908e53a 100644 (file)
@@ -52,21 +52,21 @@ void nr_start_t1timer(struct sock *sk)
 {
        struct nr_sock *nr = nr_sk(sk);
 
-       mod_timer(&nr->t1timer, jiffies + nr->t1);
+       sk_reset_timer(sk, &nr->t1timer, jiffies + nr->t1);
 }
 
 void nr_start_t2timer(struct sock *sk)
 {
        struct nr_sock *nr = nr_sk(sk);
 
-       mod_timer(&nr->t2timer, jiffies + nr->t2);
+       sk_reset_timer(sk, &nr->t2timer, jiffies + nr->t2);
 }
 
 void nr_start_t4timer(struct sock *sk)
 {
        struct nr_sock *nr = nr_sk(sk);
 
-       mod_timer(&nr->t4timer, jiffies + nr->t4);
+       sk_reset_timer(sk, &nr->t4timer, jiffies + nr->t4);
 }
 
 void nr_start_idletimer(struct sock *sk)
@@ -74,37 +74,37 @@ void nr_start_idletimer(struct sock *sk)
        struct nr_sock *nr = nr_sk(sk);
 
        if (nr->idle > 0)
-               mod_timer(&nr->idletimer, jiffies + nr->idle);
+               sk_reset_timer(sk, &nr->idletimer, jiffies + nr->idle);
 }
 
 void nr_start_heartbeat(struct sock *sk)
 {
-       mod_timer(&sk->sk_timer, jiffies + 5 * HZ);
+       sk_reset_timer(sk, &sk->sk_timer, jiffies + 5 * HZ);
 }
 
 void nr_stop_t1timer(struct sock *sk)
 {
-       del_timer(&nr_sk(sk)->t1timer);
+       sk_stop_timer(sk, &nr_sk(sk)->t1timer);
 }
 
 void nr_stop_t2timer(struct sock *sk)
 {
-       del_timer(&nr_sk(sk)->t2timer);
+       sk_stop_timer(sk, &nr_sk(sk)->t2timer);
 }
 
 void nr_stop_t4timer(struct sock *sk)
 {
-       del_timer(&nr_sk(sk)->t4timer);
+       sk_stop_timer(sk, &nr_sk(sk)->t4timer);
 }
 
 void nr_stop_idletimer(struct sock *sk)
 {
-       del_timer(&nr_sk(sk)->idletimer);
+       sk_stop_timer(sk, &nr_sk(sk)->idletimer);
 }
 
 void nr_stop_heartbeat(struct sock *sk)
 {
-       del_timer(&sk->sk_timer);
+       sk_stop_timer(sk, &sk->sk_timer);
 }
 
 int nr_t1timer_running(struct sock *sk)
index 57e0776..f54cf17 100644 (file)
@@ -276,10 +276,12 @@ static int parse_ipv6hdr(struct sk_buff *skb, struct sw_flow_key *key)
 
        nexthdr = ipv6_find_hdr(skb, &payload_ofs, -1, &frag_off, &flags);
        if (flags & IP6_FH_F_FRAG) {
-               if (frag_off)
+               if (frag_off) {
                        key->ip.frag = OVS_FRAG_TYPE_LATER;
-               else
-                       key->ip.frag = OVS_FRAG_TYPE_FIRST;
+                       key->ip.proto = nexthdr;
+                       return 0;
+               }
+               key->ip.frag = OVS_FRAG_TYPE_FIRST;
        } else {
                key->ip.frag = OVS_FRAG_TYPE_NONE;
        }
index 435a4bd..691da85 100644 (file)
@@ -500,7 +500,7 @@ static int __parse_flow_nlattrs(const struct nlattr *attr,
                        return -EINVAL;
                }
 
-               if (!nz || !is_all_zero(nla_data(nla), expected_len)) {
+               if (!nz || !is_all_zero(nla_data(nla), nla_len(nla))) {
                        attrs |= 1 << type;
                        a[type] = nla;
                }
index eedacde..1cd1d83 100644 (file)
@@ -2628,7 +2628,7 @@ static int tpacket_snd(struct packet_sock *po, struct msghdr *msg)
                addr    = saddr->sll_halen ? saddr->sll_addr : NULL;
                dev = dev_get_by_index(sock_net(&po->sk), saddr->sll_ifindex);
                if (addr && dev && saddr->sll_halen < dev->addr_len)
-                       goto out;
+                       goto out_put;
        }
 
        err = -ENXIO;
@@ -2828,7 +2828,7 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
                addr    = saddr->sll_halen ? saddr->sll_addr : NULL;
                dev = dev_get_by_index(sock_net(sk), saddr->sll_ifindex);
                if (addr && dev && saddr->sll_halen < dev->addr_len)
-                       goto out;
+                       goto out_unlock;
        }
 
        err = -ENXIO;
@@ -2887,7 +2887,8 @@ static int packet_snd(struct socket *sock, struct msghdr *msg, size_t len)
                        goto out_free;
        } else if (reserve) {
                skb_reserve(skb, -reserve);
-               if (len < reserve)
+               if (len < reserve + sizeof(struct ipv6hdr) &&
+                   dev->min_header_len != dev->hard_header_len)
                        skb_reset_network_header(skb);
        }
 
@@ -4291,7 +4292,7 @@ static int packet_set_ring(struct sock *sk, union tpacket_req_u *req_u,
                rb->frames_per_block = req->tp_block_size / req->tp_frame_size;
                if (unlikely(rb->frames_per_block == 0))
                        goto out;
-               if (unlikely(req->tp_block_size > UINT_MAX / req->tp_block_nr))
+               if (unlikely(rb->frames_per_block > UINT_MAX / req->tp_block_nr))
                        goto out;
                if (unlikely((rb->frames_per_block * req->tp_block_nr) !=
                                        req->tp_frame_nr))
index 9fc76b1..db34735 100644 (file)
@@ -132,7 +132,7 @@ static int pep_indicate(struct sock *sk, u8 id, u8 code,
        ph->utid = 0;
        ph->message_id = id;
        ph->pipe_handle = pn->pipe_handle;
-       ph->data[0] = code;
+       ph->error_code = code;
        return pn_skb_send(sk, skb, NULL);
 }
 
@@ -153,7 +153,7 @@ static int pipe_handler_request(struct sock *sk, u8 id, u8 code,
        ph->utid = id; /* whatever */
        ph->message_id = id;
        ph->pipe_handle = pn->pipe_handle;
-       ph->data[0] = code;
+       ph->error_code = code;
        return pn_skb_send(sk, skb, NULL);
 }
 
@@ -208,7 +208,7 @@ static int pep_ctrlreq_error(struct sock *sk, struct sk_buff *oskb, u8 code,
        struct pnpipehdr *ph;
        struct sockaddr_pn dst;
        u8 data[4] = {
-               oph->data[0], /* PEP type */
+               oph->pep_type, /* PEP type */
                code, /* error code, at an unusual offset */
                PAD, PAD,
        };
@@ -221,7 +221,7 @@ static int pep_ctrlreq_error(struct sock *sk, struct sk_buff *oskb, u8 code,
        ph->utid = oph->utid;
        ph->message_id = PNS_PEP_CTRL_RESP;
        ph->pipe_handle = oph->pipe_handle;
-       ph->data[0] = oph->data[1]; /* CTRL id */
+       ph->data0 = oph->data[0]; /* CTRL id */
 
        pn_skb_get_src_sockaddr(oskb, &dst);
        return pn_skb_send(sk, skb, &dst);
@@ -272,17 +272,17 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
                return -EINVAL;
 
        hdr = pnp_hdr(skb);
-       if (hdr->data[0] != PN_PEP_TYPE_COMMON) {
+       if (hdr->pep_type != PN_PEP_TYPE_COMMON) {
                net_dbg_ratelimited("Phonet unknown PEP type: %u\n",
-                                   (unsigned int)hdr->data[0]);
+                                   (unsigned int)hdr->pep_type);
                return -EOPNOTSUPP;
        }
 
-       switch (hdr->data[1]) {
+       switch (hdr->data[0]) {
        case PN_PEP_IND_FLOW_CONTROL:
                switch (pn->tx_fc) {
                case PN_LEGACY_FLOW_CONTROL:
-                       switch (hdr->data[4]) {
+                       switch (hdr->data[3]) {
                        case PEP_IND_BUSY:
                                atomic_set(&pn->tx_credits, 0);
                                break;
@@ -292,7 +292,7 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
                        }
                        break;
                case PN_ONE_CREDIT_FLOW_CONTROL:
-                       if (hdr->data[4] == PEP_IND_READY)
+                       if (hdr->data[3] == PEP_IND_READY)
                                atomic_set(&pn->tx_credits, wake = 1);
                        break;
                }
@@ -301,12 +301,12 @@ static int pipe_rcv_status(struct sock *sk, struct sk_buff *skb)
        case PN_PEP_IND_ID_MCFC_GRANT_CREDITS:
                if (pn->tx_fc != PN_MULTI_CREDIT_FLOW_CONTROL)
                        break;
-               atomic_add(wake = hdr->data[4], &pn->tx_credits);
+               atomic_add(wake = hdr->data[3], &pn->tx_credits);
                break;
 
        default:
                net_dbg_ratelimited("Phonet unknown PEP indication: %u\n",
-                                   (unsigned int)hdr->data[1]);
+                                   (unsigned int)hdr->data[0]);
                return -EOPNOTSUPP;
        }
        if (wake)
@@ -318,7 +318,7 @@ static int pipe_rcv_created(struct sock *sk, struct sk_buff *skb)
 {
        struct pep_sock *pn = pep_sk(sk);
        struct pnpipehdr *hdr = pnp_hdr(skb);
-       u8 n_sb = hdr->data[0];
+       u8 n_sb = hdr->data0;
 
        pn->rx_fc = pn->tx_fc = PN_LEGACY_FLOW_CONTROL;
        __skb_pull(skb, sizeof(*hdr));
@@ -506,7 +506,7 @@ static int pep_connresp_rcv(struct sock *sk, struct sk_buff *skb)
                return -ECONNREFUSED;
 
        /* Parse sub-blocks */
-       n_sb = hdr->data[4];
+       n_sb = hdr->data[3];
        while (n_sb > 0) {
                u8 type, buf[6], len = sizeof(buf);
                const u8 *data = pep_get_sb(skb, &type, &len, buf);
@@ -739,7 +739,7 @@ static int pipe_do_remove(struct sock *sk)
        ph->utid = 0;
        ph->message_id = PNS_PIPE_REMOVE_REQ;
        ph->pipe_handle = pn->pipe_handle;
-       ph->data[0] = PAD;
+       ph->data0 = PAD;
        return pn_skb_send(sk, skb, NULL);
 }
 
@@ -817,7 +817,7 @@ static struct sock *pep_sock_accept(struct sock *sk, int flags, int *errp,
        peer_type = hdr->other_pep_type << 8;
 
        /* Parse sub-blocks (options) */
-       n_sb = hdr->data[4];
+       n_sb = hdr->data[3];
        while (n_sb > 0) {
                u8 type, buf[1], len = sizeof(buf);
                const u8 *data = pep_get_sb(skb, &type, &len, buf);
@@ -1109,7 +1109,7 @@ static int pipe_skb_send(struct sock *sk, struct sk_buff *skb)
        ph->utid = 0;
        if (pn->aligned) {
                ph->message_id = PNS_PIPE_ALIGNED_DATA;
-               ph->data[0] = 0; /* padding */
+               ph->data0 = 0; /* padding */
        } else
                ph->message_id = PNS_PIPE_DATA;
        ph->pipe_handle = pn->pipe_handle;
index 762d2c6..17c9d9f 100644 (file)
@@ -78,10 +78,10 @@ struct rds_sock *rds_find_bound(const struct in6_addr *addr, __be16 port,
        __rds_create_bind_key(key, addr, port, scope_id);
        rcu_read_lock();
        rs = rhashtable_lookup(&bind_hash_table, key, ht_parms);
-       if (rs && !sock_flag(rds_rs_to_sk(rs), SOCK_DEAD))
-               rds_sock_addref(rs);
-       else
+       if (rs && (sock_flag(rds_rs_to_sk(rs), SOCK_DEAD) ||
+                  !refcount_inc_not_zero(&rds_rs_to_sk(rs)->sk_refcnt)))
                rs = NULL;
+
        rcu_read_unlock();
 
        rdsdebug("returning rs %p for %pI6c:%u\n", rs, addr,
index 2dcb555..4e0c36a 100644 (file)
@@ -522,7 +522,7 @@ int rds_ib_xmit(struct rds_connection *conn, struct rds_message *rm,
        if (be32_to_cpu(rm->m_inc.i_hdr.h_len) == 0)
                i = 1;
        else
-               i = ceil(be32_to_cpu(rm->m_inc.i_hdr.h_len), RDS_FRAG_SIZE);
+               i = DIV_ROUND_UP(be32_to_cpu(rm->m_inc.i_hdr.h_len), RDS_FRAG_SIZE);
 
        work_alloc = rds_ib_ring_alloc(&ic->i_send_ring, i, &pos);
        if (work_alloc == 0) {
@@ -879,7 +879,7 @@ int rds_ib_xmit_rdma(struct rds_connection *conn, struct rm_rdma_op *op)
         * Instead of knowing how to return a partial rdma read/write we insist that there
         * be enough work requests to send the entire message.
         */
-       i = ceil(op->op_count, max_sge);
+       i = DIV_ROUND_UP(op->op_count, max_sge);
 
        work_alloc = rds_ib_ring_alloc(&ic->i_send_ring, i, &pos);
        if (work_alloc != i) {
index f139420..50f13f1 100644 (file)
@@ -341,7 +341,7 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
 {
        struct rds_message *rm;
        unsigned int i;
-       int num_sgs = ceil(total_len, PAGE_SIZE);
+       int num_sgs = DIV_ROUND_UP(total_len, PAGE_SIZE);
        int extra_bytes = num_sgs * sizeof(struct scatterlist);
        int ret;
 
@@ -351,7 +351,7 @@ struct rds_message *rds_message_map_pages(unsigned long *page_addrs, unsigned in
 
        set_bit(RDS_MSG_PAGEVEC, &rm->m_flags);
        rm->m_inc.i_hdr.h_len = cpu_to_be32(total_len);
-       rm->data.op_nents = ceil(total_len, PAGE_SIZE);
+       rm->data.op_nents = DIV_ROUND_UP(total_len, PAGE_SIZE);
        rm->data.op_sg = rds_message_alloc_sgs(rm, num_sgs, &ret);
        if (!rm->data.op_sg) {
                rds_message_put(rm);
index 02ec4a3..4ffe100 100644 (file)
@@ -48,10 +48,6 @@ void rdsdebug(char *fmt, ...)
 }
 #endif
 
-/* XXX is there one of these somewhere? */
-#define ceil(x, y) \
-       ({ unsigned long __x = (x), __y = (y); (__x + __y - 1) / __y; })
-
 #define RDS_FRAG_SHIFT 12
 #define RDS_FRAG_SIZE  ((unsigned int)(1 << RDS_FRAG_SHIFT))
 
index 3d822ba..fd8b687 100644 (file)
@@ -1107,7 +1107,7 @@ int rds_sendmsg(struct socket *sock, struct msghdr *msg, size_t payload_len)
        size_t total_payload_len = payload_len, rdma_payload_len = 0;
        bool zcopy = ((msg->msg_flags & MSG_ZEROCOPY) &&
                      sock_flag(rds_rs_to_sk(rs), SOCK_ZEROCOPY));
-       int num_sgs = ceil(payload_len, PAGE_SIZE);
+       int num_sgs = DIV_ROUND_UP(payload_len, PAGE_SIZE);
        int namelen;
        struct rds_iov_vector_arr vct;
        int ind;
index 77e9f85..f2ff21d 100644 (file)
@@ -850,6 +850,7 @@ void rose_link_device_down(struct net_device *dev)
 
 /*
  *     Route a frame to an appropriate AX.25 connection.
+ *     A NULL ax25_cb indicates an internally generated frame.
  */
 int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 {
@@ -867,6 +868,10 @@ int rose_route_frame(struct sk_buff *skb, ax25_cb *ax25)
 
        if (skb->len < ROSE_MIN_LEN)
                return res;
+
+       if (!ax25)
+               return rose_loopback_queue(skb, NULL);
+
        frametype = skb->data[2];
        lci = ((skb->data[0] << 8) & 0xF00) + ((skb->data[1] << 0) & 0x0FF);
        if (frametype == ROSE_CALL_REQUEST &&
index a2522f9..96f2952 100644 (file)
@@ -418,76 +418,6 @@ u32 rxrpc_kernel_get_epoch(struct socket *sock, struct rxrpc_call *call)
 }
 EXPORT_SYMBOL(rxrpc_kernel_get_epoch);
 
-/**
- * rxrpc_kernel_check_call - Check a call's state
- * @sock: The socket the call is on
- * @call: The call to check
- * @_compl: Where to store the completion state
- * @_abort_code: Where to store any abort code
- *
- * Allow a kernel service to query the state of a call and find out the manner
- * of its termination if it has completed.  Returns -EINPROGRESS if the call is
- * still going, 0 if the call finished successfully, -ECONNABORTED if the call
- * was aborted and an appropriate error if the call failed in some other way.
- */
-int rxrpc_kernel_check_call(struct socket *sock, struct rxrpc_call *call,
-                           enum rxrpc_call_completion *_compl, u32 *_abort_code)
-{
-       if (call->state != RXRPC_CALL_COMPLETE)
-               return -EINPROGRESS;
-       smp_rmb();
-       *_compl = call->completion;
-       *_abort_code = call->abort_code;
-       return call->error;
-}
-EXPORT_SYMBOL(rxrpc_kernel_check_call);
-
-/**
- * rxrpc_kernel_retry_call - Allow a kernel service to retry a call
- * @sock: The socket the call is on
- * @call: The call to retry
- * @srx: The address of the peer to contact
- * @key: The security context to use (defaults to socket setting)
- *
- * Allow a kernel service to try resending a client call that failed due to a
- * network error to a new address.  The Tx queue is maintained intact, thereby
- * relieving the need to re-encrypt any request data that has already been
- * buffered.
- */
-int rxrpc_kernel_retry_call(struct socket *sock, struct rxrpc_call *call,
-                           struct sockaddr_rxrpc *srx, struct key *key)
-{
-       struct rxrpc_conn_parameters cp;
-       struct rxrpc_sock *rx = rxrpc_sk(sock->sk);
-       int ret;
-
-       _enter("%d{%d}", call->debug_id, atomic_read(&call->usage));
-
-       if (!key)
-               key = rx->key;
-       if (key && !key->payload.data[0])
-               key = NULL; /* a no-security key */
-
-       memset(&cp, 0, sizeof(cp));
-       cp.local                = rx->local;
-       cp.key                  = key;
-       cp.security_level       = 0;
-       cp.exclusive            = false;
-       cp.service_id           = srx->srx_service;
-
-       mutex_lock(&call->user_mutex);
-
-       ret = rxrpc_prepare_call_for_retry(rx, call);
-       if (ret == 0)
-               ret = rxrpc_retry_client_call(rx, call, &cp, srx, GFP_KERNEL);
-
-       mutex_unlock(&call->user_mutex);
-       rxrpc_put_peer(cp.peer);
-       _leave(" = %d", ret);
-       return ret;
-}
-EXPORT_SYMBOL(rxrpc_kernel_retry_call);
-
 /**
  * rxrpc_kernel_new_call_notification - Get notifications of new calls
  * @sock: The socket to intercept received messages on
index bc628ac..4b1a534 100644 (file)
@@ -476,7 +476,6 @@ enum rxrpc_call_flag {
        RXRPC_CALL_EXPOSED,             /* The call was exposed to the world */
        RXRPC_CALL_RX_LAST,             /* Received the last packet (at rxtx_top) */
        RXRPC_CALL_TX_LAST,             /* Last packet in Tx buffer (at rxtx_top) */
-       RXRPC_CALL_TX_LASTQ,            /* Last packet has been queued */
        RXRPC_CALL_SEND_PING,           /* A ping will need to be sent */
        RXRPC_CALL_PINGING,             /* Ping in process */
        RXRPC_CALL_RETRANS_TIMEOUT,     /* Retransmission due to timeout occurred */
@@ -517,6 +516,18 @@ enum rxrpc_call_state {
        NR__RXRPC_CALL_STATES
 };
 
+/*
+ * Call completion condition (state == RXRPC_CALL_COMPLETE).
+ */
+enum rxrpc_call_completion {
+       RXRPC_CALL_SUCCEEDED,           /* - Normal termination */
+       RXRPC_CALL_REMOTELY_ABORTED,    /* - call aborted by peer */
+       RXRPC_CALL_LOCALLY_ABORTED,     /* - call aborted locally on error or close */
+       RXRPC_CALL_LOCAL_ERROR,         /* - call failed due to local error */
+       RXRPC_CALL_NETWORK_ERROR,       /* - call terminated by network error */
+       NR__RXRPC_CALL_COMPLETIONS
+};
+
 /*
  * Call Tx congestion management modes.
  */
@@ -761,15 +772,9 @@ struct rxrpc_call *rxrpc_new_client_call(struct rxrpc_sock *,
                                         struct sockaddr_rxrpc *,
                                         struct rxrpc_call_params *, gfp_t,
                                         unsigned int);
-int rxrpc_retry_client_call(struct rxrpc_sock *,
-                           struct rxrpc_call *,
-                           struct rxrpc_conn_parameters *,
-                           struct sockaddr_rxrpc *,
-                           gfp_t);
 void rxrpc_incoming_call(struct rxrpc_sock *, struct rxrpc_call *,
                         struct sk_buff *);
 void rxrpc_release_call(struct rxrpc_sock *, struct rxrpc_call *);
-int rxrpc_prepare_call_for_retry(struct rxrpc_sock *, struct rxrpc_call *);
 void rxrpc_release_calls_on_socket(struct rxrpc_sock *);
 bool __rxrpc_queue_call(struct rxrpc_call *);
 bool rxrpc_queue_call(struct rxrpc_call *);
index 8f1a8f8..8aa2937 100644 (file)
@@ -324,48 +324,6 @@ error:
        return ERR_PTR(ret);
 }
 
-/*
- * Retry a call to a new address.  It is expected that the Tx queue of the call
- * will contain data previously packaged for an old call.
- */
-int rxrpc_retry_client_call(struct rxrpc_sock *rx,
-                           struct rxrpc_call *call,
-                           struct rxrpc_conn_parameters *cp,
-                           struct sockaddr_rxrpc *srx,
-                           gfp_t gfp)
-{
-       const void *here = __builtin_return_address(0);
-       int ret;
-
-       /* Set up or get a connection record and set the protocol parameters,
-        * including channel number and call ID.
-        */
-       ret = rxrpc_connect_call(rx, call, cp, srx, gfp);
-       if (ret < 0)
-               goto error;
-
-       trace_rxrpc_call(call, rxrpc_call_connected, atomic_read(&call->usage),
-                        here, NULL);
-
-       rxrpc_start_call_timer(call);
-
-       _net("CALL new %d on CONN %d", call->debug_id, call->conn->debug_id);
-
-       if (!test_and_set_bit(RXRPC_CALL_EV_RESEND, &call->events))
-               rxrpc_queue_call(call);
-
-       _leave(" = 0");
-       return 0;
-
-error:
-       rxrpc_set_call_completion(call, RXRPC_CALL_LOCAL_ERROR,
-                                 RX_CALL_DEAD, ret);
-       trace_rxrpc_call(call, rxrpc_call_error, atomic_read(&call->usage),
-                        here, ERR_PTR(ret));
-       _leave(" = %d", ret);
-       return ret;
-}
-
 /*
  * Set up an incoming call.  call->conn points to the connection.
  * This is called in BH context and isn't allowed to fail.
@@ -533,61 +491,6 @@ void rxrpc_release_call(struct rxrpc_sock *rx, struct rxrpc_call *call)
        _leave("");
 }
 
-/*
- * Prepare a kernel service call for retry.
- */
-int rxrpc_prepare_call_for_retry(struct rxrpc_sock *rx, struct rxrpc_call *call)
-{
-       const void *here = __builtin_return_address(0);
-       int i;
-       u8 last = 0;
-
-       _enter("{%d,%d}", call->debug_id, atomic_read(&call->usage));
-
-       trace_rxrpc_call(call, rxrpc_call_release, atomic_read(&call->usage),
-                        here, (const void *)call->flags);
-
-       ASSERTCMP(call->state, ==, RXRPC_CALL_COMPLETE);
-       ASSERTCMP(call->completion, !=, RXRPC_CALL_REMOTELY_ABORTED);
-       ASSERTCMP(call->completion, !=, RXRPC_CALL_LOCALLY_ABORTED);
-       ASSERT(list_empty(&call->recvmsg_link));
-
-       del_timer_sync(&call->timer);
-
-       _debug("RELEASE CALL %p (%d CONN %p)", call, call->debug_id, call->conn);
-
-       if (call->conn)
-               rxrpc_disconnect_call(call);
-
-       if (rxrpc_is_service_call(call) ||
-           !call->tx_phase ||
-           call->tx_hard_ack != 0 ||
-           call->rx_hard_ack != 0 ||
-           call->rx_top != 0)
-               return -EINVAL;
-
-       call->state = RXRPC_CALL_UNINITIALISED;
-       call->completion = RXRPC_CALL_SUCCEEDED;
-       call->call_id = 0;
-       call->cid = 0;
-       call->cong_cwnd = 0;
-       call->cong_extra = 0;
-       call->cong_ssthresh = 0;
-       call->cong_mode = 0;
-       call->cong_dup_acks = 0;
-       call->cong_cumul_acks = 0;
-       call->acks_lowest_nak = 0;
-
-       for (i = 0; i < RXRPC_RXTX_BUFF_SIZE; i++) {
-               last |= call->rxtx_annotations[i];
-               call->rxtx_annotations[i] &= RXRPC_TX_ANNO_LAST;
-               call->rxtx_annotations[i] |= RXRPC_TX_ANNO_RETRANS;
-       }
-
-       _leave(" = 0");
-       return 0;
-}
-
 /*
  * release all the calls associated with a socket
  */
index 521189f..b2adfa8 100644 (file)
@@ -562,10 +562,7 @@ static void rxrpc_activate_one_channel(struct rxrpc_connection *conn,
        clear_bit(RXRPC_CONN_FINAL_ACK_0 + channel, &conn->flags);
 
        write_lock_bh(&call->state_lock);
-       if (!test_bit(RXRPC_CALL_TX_LASTQ, &call->flags))
-               call->state = RXRPC_CALL_CLIENT_SEND_REQUEST;
-       else
-               call->state = RXRPC_CALL_CLIENT_AWAIT_REPLY;
+       call->state = RXRPC_CALL_CLIENT_SEND_REQUEST;
        write_unlock_bh(&call->state_lock);
 
        rxrpc_see_call(call);
index eaf19eb..3f7bb11 100644 (file)
@@ -596,6 +596,7 @@ error_requeue_call:
        }
 error_no_call:
        release_sock(&rx->sk);
+error_trace:
        trace_rxrpc_recvmsg(call, rxrpc_recvmsg_return, 0, 0, 0, ret);
        return ret;
 
@@ -604,7 +605,7 @@ wait_interrupted:
 wait_error:
        finish_wait(sk_sleep(&rx->sk), &wait);
        call = NULL;
-       goto error_no_call;
+       goto error_trace;
 }
 
 /**
index be01f9c..46c9312 100644 (file)
@@ -169,10 +169,8 @@ static void rxrpc_queue_packet(struct rxrpc_sock *rx, struct rxrpc_call *call,
 
        ASSERTCMP(seq, ==, call->tx_top + 1);
 
-       if (last) {
+       if (last)
                annotation |= RXRPC_TX_ANNO_LAST;
-               set_bit(RXRPC_CALL_TX_LASTQ, &call->flags);
-       }
 
        /* We have to set the timestamp before queueing as the retransmit
         * algorithm can see the packet as soon as we queue it.
@@ -386,6 +384,11 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
                                call->tx_total_len -= copy;
                }
 
+               /* check for the far side aborting the call or a network error
+                * occurring */
+               if (call->state == RXRPC_CALL_COMPLETE)
+                       goto call_terminated;
+
                /* add the packet to the send queue if it's now full */
                if (sp->remain <= 0 ||
                    (msg_data_left(msg) == 0 && !more)) {
@@ -425,16 +428,6 @@ static int rxrpc_send_data(struct rxrpc_sock *rx,
                                           notify_end_tx);
                        skb = NULL;
                }
-
-               /* Check for the far side aborting the call or a network error
-                * occurring.  If this happens, save any packet that was under
-                * construction so that in the case of a network error, the
-                * call can be retried or redirected.
-                */
-               if (call->state == RXRPC_CALL_COMPLETE) {
-                       ret = call->error;
-                       goto out;
-               }
        } while (msg_data_left(msg) > 0);
 
 success:
@@ -444,6 +437,11 @@ out:
        _leave(" = %d", ret);
        return ret;
 
+call_terminated:
+       rxrpc_free_skb(skb, rxrpc_skb_tx_freed);
+       _leave(" = %d", call->error);
+       return call->error;
+
 maybe_error:
        if (copied)
                goto success;
index c3b90fa..8b43fe0 100644 (file)
@@ -197,6 +197,15 @@ static const struct nla_policy tunnel_key_policy[TCA_TUNNEL_KEY_MAX + 1] = {
        [TCA_TUNNEL_KEY_ENC_TTL]      = { .type = NLA_U8 },
 };
 
+static void tunnel_key_release_params(struct tcf_tunnel_key_params *p)
+{
+       if (!p)
+               return;
+       if (p->tcft_action == TCA_TUNNEL_KEY_ACT_SET)
+               dst_release(&p->tcft_enc_metadata->dst);
+       kfree_rcu(p, rcu);
+}
+
 static int tunnel_key_init(struct net *net, struct nlattr *nla,
                           struct nlattr *est, struct tc_action **a,
                           int ovr, int bind, bool rtnl_held,
@@ -360,8 +369,7 @@ static int tunnel_key_init(struct net *net, struct nlattr *nla,
        rcu_swap_protected(t->params, params_new,
                           lockdep_is_held(&t->tcf_lock));
        spin_unlock_bh(&t->tcf_lock);
-       if (params_new)
-               kfree_rcu(params_new, rcu);
+       tunnel_key_release_params(params_new);
 
        if (ret == ACT_P_CREATED)
                tcf_idr_insert(tn, *a);
@@ -385,12 +393,7 @@ static void tunnel_key_release(struct tc_action *a)
        struct tcf_tunnel_key_params *params;
 
        params = rcu_dereference_protected(t->params, 1);
-       if (params) {
-               if (params->tcft_action == TCA_TUNNEL_KEY_ACT_SET)
-                       dst_release(&params->tcft_enc_metadata->dst);
-
-               kfree_rcu(params, rcu);
-       }
+       tunnel_key_release_params(params);
 }
 
 static int tunnel_key_geneve_opts_dump(struct sk_buff *skb,
index 8ce2a05..e2b5cb2 100644 (file)
@@ -1277,7 +1277,6 @@ EXPORT_SYMBOL(tcf_block_cb_unregister);
 int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
                 struct tcf_result *res, bool compat_mode)
 {
-       __be16 protocol = tc_skb_protocol(skb);
 #ifdef CONFIG_NET_CLS_ACT
        const int max_reclassify_loop = 4;
        const struct tcf_proto *orig_tp = tp;
@@ -1287,6 +1286,7 @@ int tcf_classify(struct sk_buff *skb, const struct tcf_proto *tp,
 reclassify:
 #endif
        for (; tp; tp = rcu_dereference_bh(tp->next)) {
+               __be16 protocol = tc_skb_protocol(skb);
                int err;
 
                if (tp->protocol != protocol &&
@@ -1319,7 +1319,6 @@ reset:
        }
 
        tp = first_tp;
-       protocol = tc_skb_protocol(skb);
        goto reclassify;
 #endif
 }
index dad04e7..12ca9d1 100644 (file)
@@ -1290,17 +1290,23 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        struct cls_fl_head *head = rtnl_dereference(tp->root);
        struct cls_fl_filter *fold = *arg;
        struct cls_fl_filter *fnew;
+       struct fl_flow_mask *mask;
        struct nlattr **tb;
-       struct fl_flow_mask mask = {};
        int err;
 
        if (!tca[TCA_OPTIONS])
                return -EINVAL;
 
-       tb = kcalloc(TCA_FLOWER_MAX + 1, sizeof(struct nlattr *), GFP_KERNEL);
-       if (!tb)
+       mask = kzalloc(sizeof(struct fl_flow_mask), GFP_KERNEL);
+       if (!mask)
                return -ENOBUFS;
 
+       tb = kcalloc(TCA_FLOWER_MAX + 1, sizeof(struct nlattr *), GFP_KERNEL);
+       if (!tb) {
+               err = -ENOBUFS;
+               goto errout_mask_alloc;
+       }
+
        err = nla_parse_nested(tb, TCA_FLOWER_MAX, tca[TCA_OPTIONS],
                               fl_policy, NULL);
        if (err < 0)
@@ -1343,12 +1349,12 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
                }
        }
 
-       err = fl_set_parms(net, tp, fnew, &mask, base, tb, tca[TCA_RATE], ovr,
+       err = fl_set_parms(net, tp, fnew, mask, base, tb, tca[TCA_RATE], ovr,
                           tp->chain->tmplt_priv, extack);
        if (err)
                goto errout_idr;
 
-       err = fl_check_assign_mask(head, fnew, fold, &mask);
+       err = fl_check_assign_mask(head, fnew, fold, mask);
        if (err)
                goto errout_idr;
 
@@ -1365,7 +1371,7 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        if (!tc_skip_hw(fnew->flags)) {
                err = fl_hw_replace_filter(tp, fnew, extack);
                if (err)
-                       goto errout_mask;
+                       goto errout_mask_ht;
        }
 
        if (!tc_in_hw(fnew->flags))
@@ -1392,8 +1398,13 @@ static int fl_change(struct net *net, struct sk_buff *in_skb,
        }
 
        kfree(tb);
+       kfree(mask);
        return 0;
 
+errout_mask_ht:
+       rhashtable_remove_fast(&fnew->mask->ht, &fnew->ht_node,
+                              fnew->mask->filter_ht_params);
+
 errout_mask:
        fl_mask_put(head, fnew->mask, false);
 
@@ -1405,6 +1416,8 @@ errout:
        kfree(fnew);
 errout_tb:
        kfree(tb);
+errout_mask_alloc:
+       kfree(mask);
        return err;
 }
 
index 9ccc93f..38bb882 100644 (file)
@@ -48,7 +48,7 @@ struct tcindex_data {
        u32 hash;               /* hash table size; 0 if undefined */
        u32 alloc_hash;         /* allocated size */
        u32 fall_through;       /* 0: only classify if explicit match */
-       struct rcu_head rcu;
+       struct rcu_work rwork;
 };
 
 static inline int tcindex_filter_is_set(struct tcindex_filter_result *r)
@@ -221,17 +221,11 @@ found:
        return 0;
 }
 
-static int tcindex_destroy_element(struct tcf_proto *tp,
-                                  void *arg, struct tcf_walker *walker)
-{
-       bool last;
-
-       return tcindex_delete(tp, arg, &last, NULL);
-}
-
-static void __tcindex_destroy(struct rcu_head *head)
+static void tcindex_destroy_work(struct work_struct *work)
 {
-       struct tcindex_data *p = container_of(head, struct tcindex_data, rcu);
+       struct tcindex_data *p = container_of(to_rcu_work(work),
+                                             struct tcindex_data,
+                                             rwork);
 
        kfree(p->perfect);
        kfree(p->h);
@@ -258,9 +252,11 @@ static int tcindex_filter_result_init(struct tcindex_filter_result *r)
        return tcf_exts_init(&r->exts, TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
 }
 
-static void __tcindex_partial_destroy(struct rcu_head *head)
+static void tcindex_partial_destroy_work(struct work_struct *work)
 {
-       struct tcindex_data *p = container_of(head, struct tcindex_data, rcu);
+       struct tcindex_data *p = container_of(to_rcu_work(work),
+                                             struct tcindex_data,
+                                             rwork);
 
        kfree(p->perfect);
        kfree(p);
@@ -275,7 +271,7 @@ static void tcindex_free_perfect_hash(struct tcindex_data *cp)
        kfree(cp->perfect);
 }
 
-static int tcindex_alloc_perfect_hash(struct tcindex_data *cp)
+static int tcindex_alloc_perfect_hash(struct net *net, struct tcindex_data *cp)
 {
        int i, err = 0;
 
@@ -289,6 +285,9 @@ static int tcindex_alloc_perfect_hash(struct tcindex_data *cp)
                                    TCA_TCINDEX_ACT, TCA_TCINDEX_POLICE);
                if (err < 0)
                        goto errout;
+#ifdef CONFIG_NET_CLS_ACT
+               cp->perfect[i].exts.net = net;
+#endif
        }
 
        return 0;
@@ -305,9 +304,9 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
                  struct nlattr *est, bool ovr, struct netlink_ext_ack *extack)
 {
        struct tcindex_filter_result new_filter_result, *old_r = r;
-       struct tcindex_filter_result cr;
        struct tcindex_data *cp = NULL, *oldp;
        struct tcindex_filter *f = NULL; /* make gcc behave */
+       struct tcf_result cr = {};
        int err, balloc = 0;
        struct tcf_exts e;
 
@@ -337,7 +336,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        if (p->perfect) {
                int i;
 
-               if (tcindex_alloc_perfect_hash(cp) < 0)
+               if (tcindex_alloc_perfect_hash(net, cp) < 0)
                        goto errout;
                for (i = 0; i < cp->hash; i++)
                        cp->perfect[i].res = p->perfect[i].res;
@@ -346,13 +345,10 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        cp->h = p->h;
 
        err = tcindex_filter_result_init(&new_filter_result);
-       if (err < 0)
-               goto errout1;
-       err = tcindex_filter_result_init(&cr);
        if (err < 0)
                goto errout1;
        if (old_r)
-               cr.res = r->res;
+               cr = r->res;
 
        if (tb[TCA_TCINDEX_HASH])
                cp->hash = nla_get_u32(tb[TCA_TCINDEX_HASH]);
@@ -406,7 +402,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        err = -ENOMEM;
        if (!cp->perfect && !cp->h) {
                if (valid_perfect_hash(cp)) {
-                       if (tcindex_alloc_perfect_hash(cp) < 0)
+                       if (tcindex_alloc_perfect_hash(net, cp) < 0)
                                goto errout_alloc;
                        balloc = 1;
                } else {
@@ -443,8 +439,8 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        }
 
        if (tb[TCA_TCINDEX_CLASSID]) {
-               cr.res.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
-               tcf_bind_filter(tp, &cr.res, base);
+               cr.classid = nla_get_u32(tb[TCA_TCINDEX_CLASSID]);
+               tcf_bind_filter(tp, &cr, base);
        }
 
        if (old_r && old_r != r) {
@@ -456,7 +452,7 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
        }
 
        oldp = p;
-       r->res = cr.res;
+       r->res = cr;
        tcf_exts_change(&r->exts, &e);
 
        rcu_assign_pointer(tp->root, cp);
@@ -475,10 +471,12 @@ tcindex_set_parms(struct net *net, struct tcf_proto *tp, unsigned long base,
                                ; /* nothing */
 
                rcu_assign_pointer(*fp, f);
+       } else {
+               tcf_exts_destroy(&new_filter_result.exts);
        }
 
        if (oldp)
-               call_rcu(&oldp->rcu, __tcindex_partial_destroy);
+               tcf_queue_work(&oldp->rwork, tcindex_partial_destroy_work);
        return 0;
 
 errout_alloc:
@@ -487,7 +485,6 @@ errout_alloc:
        else if (balloc == 2)
                kfree(cp->h);
 errout1:
-       tcf_exts_destroy(&cr.exts);
        tcf_exts_destroy(&new_filter_result.exts);
 errout:
        kfree(cp);
@@ -562,15 +559,34 @@ static void tcindex_destroy(struct tcf_proto *tp,
                            struct netlink_ext_ack *extack)
 {
        struct tcindex_data *p = rtnl_dereference(tp->root);
-       struct tcf_walker walker;
+       int i;
 
        pr_debug("tcindex_destroy(tp %p),p %p\n", tp, p);
-       walker.count = 0;
-       walker.skip = 0;
-       walker.fn = tcindex_destroy_element;
-       tcindex_walk(tp, &walker);
 
-       call_rcu(&p->rcu, __tcindex_destroy);
+       if (p->perfect) {
+               for (i = 0; i < p->hash; i++) {
+                       struct tcindex_filter_result *r = p->perfect + i;
+
+                       tcf_unbind_filter(tp, &r->res);
+                       if (tcf_exts_get_net(&r->exts))
+                               tcf_queue_work(&r->rwork,
+                                              tcindex_destroy_rexts_work);
+                       else
+                               __tcindex_destroy_rexts(r);
+               }
+       }
+
+       for (i = 0; p->h && i < p->hash; i++) {
+               struct tcindex_filter *f, *next;
+               bool last;
+
+               for (f = rtnl_dereference(p->h[i]); f; f = next) {
+                       next = rtnl_dereference(f->next);
+                       tcindex_delete(tp, &f->result, &last, NULL);
+               }
+       }
+
+       tcf_queue_work(&p->rwork, tcindex_destroy_work);
 }
 
 
index b910cd5..7394029 100644 (file)
@@ -1667,7 +1667,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        if (skb_is_gso(skb) && q->rate_flags & CAKE_FLAG_SPLIT_GSO) {
                struct sk_buff *segs, *nskb;
                netdev_features_t features = netif_skb_features(skb);
-               unsigned int slen = 0;
+               unsigned int slen = 0, numsegs = 0;
 
                segs = skb_gso_segment(skb, features & ~NETIF_F_GSO_MASK);
                if (IS_ERR_OR_NULL(segs))
@@ -1683,6 +1683,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                        flow_queue_add(flow, segs);
 
                        sch->q.qlen++;
+                       numsegs++;
                        slen += segs->len;
                        q->buffer_used += segs->truesize;
                        b->packets++;
@@ -1696,7 +1697,7 @@ static s32 cake_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                sch->qstats.backlog += slen;
                q->avg_window_bytes += slen;
 
-               qdisc_tree_reduce_backlog(sch, 1len);
+               qdisc_tree_reduce_backlog(sch, 1-numsegs, len-slen);
                consume_skb(skb);
        } else {
                /* not splitting */
index e689e11..c6a5029 100644 (file)
@@ -88,13 +88,14 @@ static int cbs_child_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                             struct Qdisc *child,
                             struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb);
        int err;
 
        err = child->ops->enqueue(skb, child, to_free);
        if (err != NET_XMIT_SUCCESS)
                return err;
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
 
        return NET_XMIT_SUCCESS;
index cdebaed..09b8009 100644 (file)
@@ -350,9 +350,11 @@ static struct drr_class *drr_classify(struct sk_buff *skb, struct Qdisc *sch,
 static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                       struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb);
        struct drr_sched *q = qdisc_priv(sch);
        struct drr_class *cl;
        int err = 0;
+       bool first;
 
        cl = drr_classify(skb, sch, &err);
        if (cl == NULL) {
@@ -362,6 +364,7 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return err;
        }
 
+       first = !cl->qdisc->q.qlen;
        err = qdisc_enqueue(skb, cl->qdisc, to_free);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                if (net_xmit_drop_count(err)) {
@@ -371,12 +374,12 @@ static int drr_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return err;
        }
 
-       if (cl->qdisc->q.qlen == 1) {
+       if (first) {
                list_add_tail(&cl->alist, &q->active);
                cl->deficit = cl->quantum;
        }
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
        return err;
 }
index f6f4807..4247146 100644 (file)
@@ -199,6 +199,7 @@ static struct tcf_block *dsmark_tcf_block(struct Qdisc *sch, unsigned long cl,
 static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                          struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb);
        struct dsmark_qdisc_data *p = qdisc_priv(sch);
        int err;
 
@@ -271,7 +272,7 @@ static int dsmark_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return err;
        }
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
 
        return NET_XMIT_SUCCESS;
index 66ba2ce..968a85f 100644 (file)
@@ -500,7 +500,7 @@ static void dev_watchdog_down(struct net_device *dev)
  *     netif_carrier_on - set carrier
  *     @dev: network device
  *
- * Device has detected that carrier.
+ * Device has detected acquisition of carrier.
  */
 void netif_carrier_on(struct net_device *dev)
 {
index b18ec1f..24cc220 100644 (file)
@@ -1539,8 +1539,10 @@ hfsc_dump_qdisc(struct Qdisc *sch, struct sk_buff *skb)
 static int
 hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb);
        struct hfsc_class *cl;
        int uninitialized_var(err);
+       bool first;
 
        cl = hfsc_classify(skb, sch, &err);
        if (cl == NULL) {
@@ -1550,6 +1552,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
                return err;
        }
 
+       first = !cl->qdisc->q.qlen;
        err = qdisc_enqueue(skb, cl->qdisc, to_free);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                if (net_xmit_drop_count(err)) {
@@ -1559,9 +1562,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
                return err;
        }
 
-       if (cl->qdisc->q.qlen == 1) {
-               unsigned int len = qdisc_pkt_len(skb);
-
+       if (first) {
                if (cl->cl_flags & HFSC_RSC)
                        init_ed(cl, len);
                if (cl->cl_flags & HFSC_FSC)
@@ -1576,7 +1577,7 @@ hfsc_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
 
        }
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
 
        return NET_XMIT_SUCCESS;
index 58b4494..30f9da7 100644 (file)
@@ -581,6 +581,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                       struct sk_buff **to_free)
 {
        int uninitialized_var(ret);
+       unsigned int len = qdisc_pkt_len(skb);
        struct htb_sched *q = qdisc_priv(sch);
        struct htb_class *cl = htb_classify(skb, sch, &ret);
 
@@ -610,7 +611,7 @@ static int htb_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                htb_activate(q, cl);
        }
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
        return NET_XMIT_SUCCESS;
 }
index cdf6870..847141c 100644 (file)
@@ -72,6 +72,7 @@ prio_classify(struct sk_buff *skb, struct Qdisc *sch, int *qerr)
 static int
 prio_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb);
        struct Qdisc *qdisc;
        int ret;
 
@@ -88,7 +89,7 @@ prio_enqueue(struct sk_buff *skb, struct Qdisc *sch, struct sk_buff **to_free)
 
        ret = qdisc_enqueue(skb, qdisc, to_free);
        if (ret == NET_XMIT_SUCCESS) {
-               qdisc_qstats_backlog_inc(sch, skb);
+               sch->qstats.backlog += len;
                sch->q.qlen++;
                return NET_XMIT_SUCCESS;
        }
index dc37c4e..29f5c4a 100644 (file)
@@ -1210,10 +1210,12 @@ static struct qfq_aggregate *qfq_choose_next_agg(struct qfq_sched *q)
 static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                       struct sk_buff **to_free)
 {
+       unsigned int len = qdisc_pkt_len(skb), gso_segs;
        struct qfq_sched *q = qdisc_priv(sch);
        struct qfq_class *cl;
        struct qfq_aggregate *agg;
        int err = 0;
+       bool first;
 
        cl = qfq_classify(skb, sch, &err);
        if (cl == NULL) {
@@ -1224,17 +1226,18 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
        }
        pr_debug("qfq_enqueue: cl = %x\n", cl->common.classid);
 
-       if (unlikely(cl->agg->lmax < qdisc_pkt_len(skb))) {
+       if (unlikely(cl->agg->lmax < len)) {
                pr_debug("qfq: increasing maxpkt from %u to %u for class %u",
-                        cl->agg->lmax, qdisc_pkt_len(skb), cl->common.classid);
-               err = qfq_change_agg(sch, cl, cl->agg->class_weight,
-                                    qdisc_pkt_len(skb));
+                        cl->agg->lmax, len, cl->common.classid);
+               err = qfq_change_agg(sch, cl, cl->agg->class_weight, len);
                if (err) {
                        cl->qstats.drops++;
                        return qdisc_drop(skb, sch, to_free);
                }
        }
 
+       gso_segs = skb_is_gso(skb) ? skb_shinfo(skb)->gso_segs : 1;
+       first = !cl->qdisc->q.qlen;
        err = qdisc_enqueue(skb, cl->qdisc, to_free);
        if (unlikely(err != NET_XMIT_SUCCESS)) {
                pr_debug("qfq_enqueue: enqueue failed %d\n", err);
@@ -1245,16 +1248,17 @@ static int qfq_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return err;
        }
 
-       bstats_update(&cl->bstats, skb);
-       qdisc_qstats_backlog_inc(sch, skb);
+       cl->bstats.bytes += len;
+       cl->bstats.packets += gso_segs;
+       sch->qstats.backlog += len;
        ++sch->q.qlen;
 
        agg = cl->agg;
        /* if the queue was not empty, then done here */
-       if (cl->qdisc->q.qlen != 1) {
+       if (!first) {
                if (unlikely(skb == cl->qdisc->ops->peek(cl->qdisc)) &&
                    list_first_entry(&agg->active, struct qfq_class, alist)
-                   == cl && cl->deficit < qdisc_pkt_len(skb))
+                   == cl && cl->deficit < len)
                        list_move_tail(&cl->alist, &agg->active);
 
                return err;
index 942dcca..7f272a9 100644 (file)
@@ -185,6 +185,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                       struct sk_buff **to_free)
 {
        struct tbf_sched_data *q = qdisc_priv(sch);
+       unsigned int len = qdisc_pkt_len(skb);
        int ret;
 
        if (qdisc_pkt_len(skb) > q->max_size) {
@@ -200,7 +201,7 @@ static int tbf_enqueue(struct sk_buff *skb, struct Qdisc *sch,
                return ret;
        }
 
-       qdisc_qstats_backlog_inc(sch, skb);
+       sch->qstats.backlog += len;
        sch->q.qlen++;
        return NET_XMIT_SUCCESS;
 }
index 078f01a..435847d 100644 (file)
@@ -256,6 +256,7 @@ static size_t inet_assoc_attr_size(struct sctp_association *asoc)
                + nla_total_size(1) /* INET_DIAG_TOS */
                + nla_total_size(1) /* INET_DIAG_TCLASS */
                + nla_total_size(4) /* INET_DIAG_MARK */
+               + nla_total_size(4) /* INET_DIAG_CLASS_ID */
                + nla_total_size(addrlen * asoc->peer.transport_count)
                + nla_total_size(addrlen * addrcnt)
                + nla_total_size(sizeof(struct inet_diag_meminfo))
index b9ed271..6200cd2 100644 (file)
@@ -97,11 +97,9 @@ static int sctp_inet6addr_event(struct notifier_block *this, unsigned long ev,
 
        switch (ev) {
        case NETDEV_UP:
-               addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
+               addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
                if (addr) {
                        addr->a.v6.sin6_family = AF_INET6;
-                       addr->a.v6.sin6_port = 0;
-                       addr->a.v6.sin6_flowinfo = 0;
                        addr->a.v6.sin6_addr = ifa->addr;
                        addr->a.v6.sin6_scope_id = ifa->idev->dev->ifindex;
                        addr->valid = 1;
@@ -282,7 +280,8 @@ static void sctp_v6_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
 
        if (saddr) {
                fl6->saddr = saddr->v6.sin6_addr;
-               fl6->fl6_sport = saddr->v6.sin6_port;
+               if (!fl6->fl6_sport)
+                       fl6->fl6_sport = saddr->v6.sin6_port;
 
                pr_debug("src=%pI6 - ", &fl6->saddr);
        }
@@ -434,7 +433,6 @@ static void sctp_v6_copy_addrlist(struct list_head *addrlist,
                addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
                if (addr) {
                        addr->a.v6.sin6_family = AF_INET6;
-                       addr->a.v6.sin6_port = 0;
                        addr->a.v6.sin6_addr = ifp->addr;
                        addr->a.v6.sin6_scope_id = dev->ifindex;
                        addr->valid = 1;
index 123e9f2..edfcf16 100644 (file)
@@ -36,6 +36,7 @@ static __le32 sctp_gso_make_checksum(struct sk_buff *skb)
 {
        skb->ip_summed = CHECKSUM_NONE;
        skb->csum_not_inet = 0;
+       gso_reset_checksum(skb, ~0);
        return sctp_compute_cksum(skb, skb_transport_offset(skb));
 }
 
index d5878ae..6abc8b2 100644 (file)
@@ -101,7 +101,6 @@ static void sctp_v4_copy_addrlist(struct list_head *addrlist,
                addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
                if (addr) {
                        addr->a.v4.sin_family = AF_INET;
-                       addr->a.v4.sin_port = 0;
                        addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
                        addr->valid = 1;
                        INIT_LIST_HEAD(&addr->list);
@@ -441,7 +440,8 @@ static void sctp_v4_get_dst(struct sctp_transport *t, union sctp_addr *saddr,
        }
        if (saddr) {
                fl4->saddr = saddr->v4.sin_addr.s_addr;
-               fl4->fl4_sport = saddr->v4.sin_port;
+               if (!fl4->fl4_sport)
+                       fl4->fl4_sport = saddr->v4.sin_port;
        }
 
        pr_debug("%s: dst:%pI4, src:%pI4 - ", __func__, &fl4->daddr,
@@ -776,10 +776,9 @@ static int sctp_inetaddr_event(struct notifier_block *this, unsigned long ev,
 
        switch (ev) {
        case NETDEV_UP:
-               addr = kmalloc(sizeof(struct sctp_sockaddr_entry), GFP_ATOMIC);
+               addr = kzalloc(sizeof(*addr), GFP_ATOMIC);
                if (addr) {
                        addr->a.v4.sin_family = AF_INET;
-                       addr->a.v4.sin_port = 0;
                        addr->a.v4.sin_addr.s_addr = ifa->ifa_local;
                        addr->valid = 1;
                        spin_lock_bh(&net->sctp.local_addr_lock);
index f4ac6c5..d05c576 100644 (file)
@@ -495,7 +495,10 @@ struct sctp_chunk *sctp_make_init_ack(const struct sctp_association *asoc,
         *
         * [INIT ACK back to where the INIT came from.]
         */
-       retval->transport = chunk->transport;
+       if (chunk->transport)
+               retval->transport =
+                       sctp_assoc_lookup_paddr(asoc,
+                                               &chunk->transport->ipaddr);
 
        retval->subh.init_hdr =
                sctp_addto_chunk(retval, sizeof(initack), &initack);
@@ -642,8 +645,10 @@ struct sctp_chunk *sctp_make_cookie_ack(const struct sctp_association *asoc,
         *
         * [COOKIE ACK back to where the COOKIE ECHO came from.]
         */
-       if (retval && chunk)
-               retval->transport = chunk->transport;
+       if (retval && chunk && chunk->transport)
+               retval->transport =
+                       sctp_assoc_lookup_paddr(asoc,
+                                               &chunk->transport->ipaddr);
 
        return retval;
 }
index f93c3cf..65d6d04 100644 (file)
@@ -2027,7 +2027,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
        struct sctp_endpoint *ep = sctp_sk(sk)->ep;
        struct sctp_transport *transport = NULL;
        struct sctp_sndrcvinfo _sinfo, *sinfo;
-       struct sctp_association *asoc;
+       struct sctp_association *asoc, *tmp;
        struct sctp_cmsgs cmsgs;
        union sctp_addr *daddr;
        bool new = false;
@@ -2053,7 +2053,7 @@ static int sctp_sendmsg(struct sock *sk, struct msghdr *msg, size_t msg_len)
 
        /* SCTP_SENDALL process */
        if ((sflags & SCTP_SENDALL) && sctp_style(sk, UDP)) {
-               list_for_each_entry(asoc, &ep->asocs, asocs) {
+               list_for_each_entry_safe(asoc, tmp, &ep->asocs, asocs) {
                        err = sctp_sendmsg_check_sflags(asoc, sflags, msg,
                                                        msg_len);
                        if (err == 0)
index 3892e76..2936ed1 100644 (file)
@@ -84,6 +84,19 @@ static void fa_zero(struct flex_array *fa, size_t index, size_t count)
        }
 }
 
+static size_t fa_index(struct flex_array *fa, void *elem, size_t count)
+{
+       size_t index = 0;
+
+       while (count--) {
+               if (elem == flex_array_get(fa, index))
+                       break;
+               index++;
+       }
+
+       return index;
+}
+
 /* Migrates chunks from stream queues to new stream queues if needed,
  * but not across associations. Also, removes those chunks to streams
  * higher than the new max.
@@ -131,8 +144,10 @@ static void sctp_stream_outq_migrate(struct sctp_stream *stream,
                }
        }
 
-       for (i = outcnt; i < stream->outcnt; i++)
+       for (i = outcnt; i < stream->outcnt; i++) {
                kfree(SCTP_SO(stream, i)->ext);
+               SCTP_SO(stream, i)->ext = NULL;
+       }
 }
 
 static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt,
@@ -147,6 +162,13 @@ static int sctp_stream_alloc_out(struct sctp_stream *stream, __u16 outcnt,
 
        if (stream->out) {
                fa_copy(out, stream->out, 0, min(outcnt, stream->outcnt));
+               if (stream->out_curr) {
+                       size_t index = fa_index(stream->out, stream->out_curr,
+                                               stream->outcnt);
+
+                       BUG_ON(index == stream->outcnt);
+                       stream->out_curr = flex_array_get(out, index);
+               }
                fa_free(stream->out);
        }
 
@@ -585,9 +607,9 @@ struct sctp_chunk *sctp_process_strreset_outreq(
        struct sctp_strreset_outreq *outreq = param.v;
        struct sctp_stream *stream = &asoc->stream;
        __u32 result = SCTP_STRRESET_DENIED;
-       __u16 i, nums, flags = 0;
        __be16 *str_p = NULL;
        __u32 request_seq;
+       __u16 i, nums;
 
        request_seq = ntohl(outreq->request_seq);
 
@@ -615,6 +637,15 @@ struct sctp_chunk *sctp_process_strreset_outreq(
        if (!(asoc->strreset_enable & SCTP_ENABLE_RESET_STREAM_REQ))
                goto out;
 
+       nums = (ntohs(param.p->length) - sizeof(*outreq)) / sizeof(__u16);
+       str_p = outreq->list_of_streams;
+       for (i = 0; i < nums; i++) {
+               if (ntohs(str_p[i]) >= stream->incnt) {
+                       result = SCTP_STRRESET_ERR_WRONG_SSN;
+                       goto out;
+               }
+       }
+
        if (asoc->strreset_chunk) {
                if (!sctp_chunk_lookup_strreset_param(
                                asoc, outreq->response_seq,
@@ -637,32 +668,19 @@ struct sctp_chunk *sctp_process_strreset_outreq(
                        sctp_chunk_put(asoc->strreset_chunk);
                        asoc->strreset_chunk = NULL;
                }
-
-               flags = SCTP_STREAM_RESET_INCOMING_SSN;
        }
 
-       nums = (ntohs(param.p->length) - sizeof(*outreq)) / sizeof(__u16);
-       if (nums) {
-               str_p = outreq->list_of_streams;
-               for (i = 0; i < nums; i++) {
-                       if (ntohs(str_p[i]) >= stream->incnt) {
-                               result = SCTP_STRRESET_ERR_WRONG_SSN;
-                               goto out;
-                       }
-               }
-
+       if (nums)
                for (i = 0; i < nums; i++)
                        SCTP_SI(stream, ntohs(str_p[i]))->mid = 0;
-       } else {
+       else
                for (i = 0; i < stream->incnt; i++)
                        SCTP_SI(stream, i)->mid = 0;
-       }
 
        result = SCTP_STRRESET_PERFORMED;
 
        *evp = sctp_ulpevent_make_stream_reset_event(asoc,
-               flags | SCTP_STREAM_RESET_OUTGOING_SSN, nums, str_p,
-               GFP_ATOMIC);
+               SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC);
 
 out:
        sctp_update_strreset_result(asoc, result);
@@ -738,9 +756,6 @@ struct sctp_chunk *sctp_process_strreset_inreq(
 
        result = SCTP_STRRESET_PERFORMED;
 
-       *evp = sctp_ulpevent_make_stream_reset_event(asoc,
-               SCTP_STREAM_RESET_INCOMING_SSN, nums, str_p, GFP_ATOMIC);
-
 out:
        sctp_update_strreset_result(asoc, result);
 err:
@@ -873,6 +888,14 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
        if (!(asoc->strreset_enable & SCTP_ENABLE_CHANGE_ASSOC_REQ))
                goto out;
 
+       in = ntohs(addstrm->number_of_streams);
+       incnt = stream->incnt + in;
+       if (!in || incnt > SCTP_MAX_STREAM)
+               goto out;
+
+       if (sctp_stream_alloc_in(stream, incnt, GFP_ATOMIC))
+               goto out;
+
        if (asoc->strreset_chunk) {
                if (!sctp_chunk_lookup_strreset_param(
                        asoc, 0, SCTP_PARAM_RESET_ADD_IN_STREAMS)) {
@@ -896,14 +919,6 @@ struct sctp_chunk *sctp_process_strreset_addstrm_out(
                }
        }
 
-       in = ntohs(addstrm->number_of_streams);
-       incnt = stream->incnt + in;
-       if (!in || incnt > SCTP_MAX_STREAM)
-               goto out;
-
-       if (sctp_stream_alloc_in(stream, incnt, GFP_ATOMIC))
-               goto out;
-
        stream->incnt = incnt;
 
        result = SCTP_STRRESET_PERFORMED;
@@ -973,9 +988,6 @@ struct sctp_chunk *sctp_process_strreset_addstrm_in(
 
        result = SCTP_STRRESET_PERFORMED;
 
-       *evp = sctp_ulpevent_make_stream_change_event(asoc,
-               0, 0, ntohs(addstrm->number_of_streams), GFP_ATOMIC);
-
 out:
        sctp_update_strreset_result(asoc, result);
 err:
@@ -1036,10 +1048,10 @@ struct sctp_chunk *sctp_process_strreset_resp(
                                        sout->mid_uo = 0;
                                }
                        }
-
-                       flags = SCTP_STREAM_RESET_OUTGOING_SSN;
                }
 
+               flags |= SCTP_STREAM_RESET_OUTGOING_SSN;
+
                for (i = 0; i < stream->outcnt; i++)
                        SCTP_SO(stream, i)->state = SCTP_STREAM_OPEN;
 
@@ -1058,6 +1070,8 @@ struct sctp_chunk *sctp_process_strreset_resp(
                nums = (ntohs(inreq->param_hdr.length) - sizeof(*inreq)) /
                       sizeof(__u16);
 
+               flags |= SCTP_STREAM_RESET_INCOMING_SSN;
+
                *evp = sctp_ulpevent_make_stream_reset_event(asoc, flags,
                        nums, str_p, GFP_ATOMIC);
        } else if (req->type == SCTP_PARAM_RESET_TSN_REQUEST) {
index 033696e..ad158d3 100644 (file)
@@ -207,7 +207,8 @@ void sctp_transport_reset_hb_timer(struct sctp_transport *transport)
 
        /* When a data chunk is sent, reset the heartbeat interval.  */
        expires = jiffies + sctp_transport_timeout(transport);
-       if (time_before(transport->hb_timer.expires, expires) &&
+       if ((time_before(transport->hb_timer.expires, expires) ||
+            !timer_pending(&transport->hb_timer)) &&
            !mod_timer(&transport->hb_timer,
                       expires + prandom_u32_max(transport->rto)))
                sctp_transport_hold(transport);
index c4da4a7..b04a813 100644 (file)
@@ -146,6 +146,9 @@ static int smc_release(struct socket *sock)
                sock_set_flag(sk, SOCK_DEAD);
                sk->sk_shutdown |= SHUTDOWN_MASK;
        }
+
+       sk->sk_prot->unhash(sk);
+
        if (smc->clcsock) {
                if (smc->use_fallback && sk->sk_state == SMC_LISTEN) {
                        /* wake up clcsock accept */
@@ -170,7 +173,6 @@ static int smc_release(struct socket *sock)
                smc_conn_free(&smc->conn);
        release_sock(sk);
 
-       sk->sk_prot->unhash(sk);
        sock_put(sk); /* final sock_put */
 out:
        return rc;
@@ -1503,6 +1505,11 @@ static int smc_recvmsg(struct socket *sock, struct msghdr *msg, size_t len,
 
        smc = smc_sk(sk);
        lock_sock(sk);
+       if (sk->sk_state == SMC_CLOSED && (sk->sk_shutdown & RCV_SHUTDOWN)) {
+               /* socket was connected before, no more data to read */
+               rc = 0;
+               goto out;
+       }
        if ((sk->sk_state == SMC_INIT) ||
            (sk->sk_state == SMC_LISTEN) ||
            (sk->sk_state == SMC_CLOSED))
@@ -1838,7 +1845,11 @@ static ssize_t smc_splice_read(struct socket *sock, loff_t *ppos,
 
        smc = smc_sk(sk);
        lock_sock(sk);
-
+       if (sk->sk_state == SMC_CLOSED && (sk->sk_shutdown & RCV_SHUTDOWN)) {
+               /* socket was connected before, no more data to read */
+               rc = 0;
+               goto out;
+       }
        if (sk->sk_state == SMC_INIT ||
            sk->sk_state == SMC_LISTEN ||
            sk->sk_state == SMC_CLOSED)
index 5721416..adbdf19 100644 (file)
@@ -113,9 +113,9 @@ struct smc_host_cdc_msg {           /* Connection Data Control message */
 } __aligned(8);
 
 enum smc_urg_state {
-       SMC_URG_VALID,                  /* data present */
-       SMC_URG_NOTYET,                 /* data pending */
-       SMC_URG_READ                    /* data was already read */
+       SMC_URG_VALID   = 1,                    /* data present */
+       SMC_URG_NOTYET  = 2,                    /* data pending */
+       SMC_URG_READ    = 3,                    /* data was already read */
 };
 
 struct smc_connection {
index db83332..fb07ad8 100644 (file)
 
 /********************************** send *************************************/
 
-struct smc_cdc_tx_pend {
-       struct smc_connection   *conn;          /* socket connection */
-       union smc_host_cursor   cursor; /* tx sndbuf cursor sent */
-       union smc_host_cursor   p_cursor;       /* rx RMBE cursor produced */
-       u16                     ctrl_seq;       /* conn. tx sequence # */
-};
-
 /* handler for send/transmission completion of a CDC msg */
 static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd,
                               struct smc_link *link,
@@ -61,12 +54,14 @@ static void smc_cdc_tx_handler(struct smc_wr_tx_pend_priv *pnd_snd,
 
 int smc_cdc_get_free_slot(struct smc_connection *conn,
                          struct smc_wr_buf **wr_buf,
+                         struct smc_rdma_wr **wr_rdma_buf,
                          struct smc_cdc_tx_pend **pend)
 {
        struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK];
        int rc;
 
        rc = smc_wr_tx_get_free_slot(link, smc_cdc_tx_handler, wr_buf,
+                                    wr_rdma_buf,
                                     (struct smc_wr_tx_pend_priv **)pend);
        if (!conn->alert_token_local)
                /* abnormal termination */
@@ -96,6 +91,7 @@ int smc_cdc_msg_send(struct smc_connection *conn,
                     struct smc_wr_buf *wr_buf,
                     struct smc_cdc_tx_pend *pend)
 {
+       union smc_host_cursor cfed;
        struct smc_link *link;
        int rc;
 
@@ -105,12 +101,10 @@ int smc_cdc_msg_send(struct smc_connection *conn,
 
        conn->tx_cdc_seq++;
        conn->local_tx_ctrl.seqno = conn->tx_cdc_seq;
-       smc_host_msg_to_cdc((struct smc_cdc_msg *)wr_buf,
-                           &conn->local_tx_ctrl, conn);
+       smc_host_msg_to_cdc((struct smc_cdc_msg *)wr_buf, conn, &cfed);
        rc = smc_wr_tx_send(link, (struct smc_wr_tx_pend_priv *)pend);
        if (!rc)
-               smc_curs_copy(&conn->rx_curs_confirmed,
-                             &conn->local_tx_ctrl.cons, conn);
+               smc_curs_copy(&conn->rx_curs_confirmed, &cfed, conn);
 
        return rc;
 }
@@ -121,11 +115,14 @@ static int smcr_cdc_get_slot_and_msg_send(struct smc_connection *conn)
        struct smc_wr_buf *wr_buf;
        int rc;
 
-       rc = smc_cdc_get_free_slot(conn, &wr_buf, &pend);
+       rc = smc_cdc_get_free_slot(conn, &wr_buf, NULL, &pend);
        if (rc)
                return rc;
 
-       return smc_cdc_msg_send(conn, wr_buf, pend);
+       spin_lock_bh(&conn->send_lock);
+       rc = smc_cdc_msg_send(conn, wr_buf, pend);
+       spin_unlock_bh(&conn->send_lock);
+       return rc;
 }
 
 int smc_cdc_get_slot_and_msg_send(struct smc_connection *conn)
index b5bfe38..f1cdde9 100644 (file)
@@ -160,7 +160,9 @@ static inline void smcd_curs_copy(union smcd_cdc_cursor *tgt,
 #endif
 }
 
-/* calculate cursor difference between old and new, where old <= new */
+/* calculate cursor difference between old and new, where old <= new and
+ * difference cannot exceed size
+ */
 static inline int smc_curs_diff(unsigned int size,
                                union smc_host_cursor *old,
                                union smc_host_cursor *new)
@@ -185,28 +187,51 @@ static inline int smc_curs_comp(unsigned int size,
        return smc_curs_diff(size, old, new);
 }
 
+/* calculate cursor difference between old and new, where old <= new and
+ * difference may exceed size
+ */
+static inline int smc_curs_diff_large(unsigned int size,
+                                     union smc_host_cursor *old,
+                                     union smc_host_cursor *new)
+{
+       if (old->wrap < new->wrap)
+               return min_t(int,
+                            (size - old->count) + new->count +
+                            (new->wrap - old->wrap - 1) * size,
+                            size);
+
+       if (old->wrap > new->wrap) /* wrap has switched from 0xffff to 0x0000 */
+               return min_t(int,
+                            (size - old->count) + new->count +
+                            (new->wrap + 0xffff - old->wrap) * size,
+                            size);
+
+       return max_t(int, 0, (new->count - old->count));
+}
+
 static inline void smc_host_cursor_to_cdc(union smc_cdc_cursor *peer,
                                          union smc_host_cursor *local,
+                                         union smc_host_cursor *save,
                                          struct smc_connection *conn)
 {
-       union smc_host_cursor temp;
-
-       smc_curs_copy(&temp, local, conn);
-       peer->count = htonl(temp.count);
-       peer->wrap = htons(temp.wrap);
+       smc_curs_copy(save, local, conn);
+       peer->count = htonl(save->count);
+       peer->wrap = htons(save->wrap);
        /* peer->reserved = htons(0); must be ensured by caller */
 }
 
 static inline void smc_host_msg_to_cdc(struct smc_cdc_msg *peer,
-                                      struct smc_host_cdc_msg *local,
-                                      struct smc_connection *conn)
+                                      struct smc_connection *conn,
+                                      union smc_host_cursor *save)
 {
+       struct smc_host_cdc_msg *local = &conn->local_tx_ctrl;
+
        peer->common.type = local->common.type;
        peer->len = local->len;
        peer->seqno = htons(local->seqno);
        peer->token = htonl(local->token);
-       smc_host_cursor_to_cdc(&peer->prod, &local->prod, conn);
-       smc_host_cursor_to_cdc(&peer->cons, &local->cons, conn);
+       smc_host_cursor_to_cdc(&peer->prod, &local->prod, save, conn);
+       smc_host_cursor_to_cdc(&peer->cons, &local->cons, save, conn);
        peer->prod_flags = local->prod_flags;
        peer->conn_state_flags = local->conn_state_flags;
 }
@@ -270,10 +295,16 @@ static inline void smc_cdc_msg_to_host(struct smc_host_cdc_msg *local,
                smcr_cdc_msg_to_host(local, peer, conn);
 }
 
-struct smc_cdc_tx_pend;
+struct smc_cdc_tx_pend {
+       struct smc_connection   *conn;          /* socket connection */
+       union smc_host_cursor   cursor;         /* tx sndbuf cursor sent */
+       union smc_host_cursor   p_cursor;       /* rx RMBE cursor produced */
+       u16                     ctrl_seq;       /* conn. tx sequence # */
+};
 
 int smc_cdc_get_free_slot(struct smc_connection *conn,
                          struct smc_wr_buf **wr_buf,
+                         struct smc_rdma_wr **wr_rdma_buf,
                          struct smc_cdc_tx_pend **pend);
 void smc_cdc_tx_dismiss_slots(struct smc_connection *conn);
 int smc_cdc_msg_send(struct smc_connection *conn, struct smc_wr_buf *wr_buf,
index 776e9df..d53fd58 100644 (file)
@@ -378,7 +378,7 @@ int smc_clc_send_decline(struct smc_sock *smc, u32 peer_diag_info)
        vec.iov_len = sizeof(struct smc_clc_msg_decline);
        len = kernel_sendmsg(smc->clcsock, &msg, &vec, 1,
                             sizeof(struct smc_clc_msg_decline));
-       if (len < sizeof(struct smc_clc_msg_decline))
+       if (len < 0 || len < sizeof(struct smc_clc_msg_decline))
                len = -EPROTO;
        return len > 0 ? 0 : len;
 }
index ea2b87f..e39cadd 100644 (file)
@@ -345,14 +345,7 @@ static void smc_close_passive_work(struct work_struct *work)
 
        switch (sk->sk_state) {
        case SMC_INIT:
-               if (atomic_read(&conn->bytes_to_rcv) ||
-                   (rxflags->peer_done_writing &&
-                    !smc_cdc_rxed_any_close(conn))) {
-                       sk->sk_state = SMC_APPCLOSEWAIT1;
-               } else {
-                       sk->sk_state = SMC_CLOSED;
-                       sock_put(sk); /* passive closing */
-               }
+               sk->sk_state = SMC_APPCLOSEWAIT1;
                break;
        case SMC_ACTIVE:
                sk->sk_state = SMC_APPCLOSEWAIT1;
index 35c1cdc..aa1c551 100644 (file)
@@ -128,6 +128,8 @@ static void smc_lgr_unregister_conn(struct smc_connection *conn)
 {
        struct smc_link_group *lgr = conn->lgr;
 
+       if (!lgr)
+               return;
        write_lock_bh(&lgr->conns_lock);
        if (conn->alert_token_local) {
                __smc_lgr_unregister_conn(conn);
@@ -300,13 +302,13 @@ static void smc_buf_unuse(struct smc_connection *conn,
                conn->sndbuf_desc->used = 0;
        if (conn->rmb_desc) {
                if (!conn->rmb_desc->regerr) {
-                       conn->rmb_desc->used = 0;
                        if (!lgr->is_smcd) {
                                /* unregister rmb with peer */
                                smc_llc_do_delete_rkey(
                                                &lgr->lnk[SMC_SINGLE_LINK],
                                                conn->rmb_desc);
                        }
+                       conn->rmb_desc->used = 0;
                } else {
                        /* buf registration failed, reuse not possible */
                        write_lock_bh(&lgr->rmbs_lock);
@@ -628,6 +630,8 @@ int smc_conn_create(struct smc_sock *smc, bool is_smcd, int srv_first_contact,
                        local_contact = SMC_REUSE_CONTACT;
                        conn->lgr = lgr;
                        smc_lgr_register_conn(conn); /* add smc conn to lgr */
+                       if (delayed_work_pending(&lgr->free_work))
+                               cancel_delayed_work(&lgr->free_work);
                        write_unlock_bh(&lgr->conns_lock);
                        break;
                }
index b002879..8806d2a 100644 (file)
@@ -52,6 +52,24 @@ enum smc_wr_reg_state {
        FAILED          /* ib_wr_reg_mr response: failure */
 };
 
+struct smc_rdma_sge {                          /* sges for RDMA writes */
+       struct ib_sge           wr_tx_rdma_sge[SMC_IB_MAX_SEND_SGE];
+};
+
+#define SMC_MAX_RDMA_WRITES    2               /* max. # of RDMA writes per
+                                                * message send
+                                                */
+
+struct smc_rdma_sges {                         /* sges per message send */
+       struct smc_rdma_sge     tx_rdma_sge[SMC_MAX_RDMA_WRITES];
+};
+
+struct smc_rdma_wr {                           /* work requests per message
+                                                * send
+                                                */
+       struct ib_rdma_wr       wr_tx_rdma[SMC_MAX_RDMA_WRITES];
+};
+
 struct smc_link {
        struct smc_ib_device    *smcibdev;      /* ib-device */
        u8                      ibport;         /* port - values 1 | 2 */
@@ -64,6 +82,8 @@ struct smc_link {
        struct smc_wr_buf       *wr_tx_bufs;    /* WR send payload buffers */
        struct ib_send_wr       *wr_tx_ibs;     /* WR send meta data */
        struct ib_sge           *wr_tx_sges;    /* WR send gather meta data */
+       struct smc_rdma_sges    *wr_tx_rdma_sges;/*RDMA WRITE gather meta data*/
+       struct smc_rdma_wr      *wr_tx_rdmas;   /* WR RDMA WRITE */
        struct smc_wr_tx_pend   *wr_tx_pends;   /* WR send waiting for CQE */
        /* above four vectors have wr_tx_cnt elements and use the same index */
        dma_addr_t              wr_tx_dma_addr; /* DMA address of wr_tx_bufs */
index e519ef2..76487a1 100644 (file)
@@ -289,8 +289,8 @@ int smc_ib_create_protection_domain(struct smc_link *lnk)
 
 static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv)
 {
-       struct smc_ib_device *smcibdev =
-               (struct smc_ib_device *)ibevent->device;
+       struct smc_link *lnk = (struct smc_link *)priv;
+       struct smc_ib_device *smcibdev = lnk->smcibdev;
        u8 port_idx;
 
        switch (ibevent->event) {
@@ -298,7 +298,7 @@ static void smc_ib_qp_event_handler(struct ib_event *ibevent, void *priv)
        case IB_EVENT_GID_CHANGE:
        case IB_EVENT_PORT_ERR:
        case IB_EVENT_QP_ACCESS_ERR:
-               port_idx = ibevent->element.port_num - 1;
+               port_idx = ibevent->element.qp->port - 1;
                set_bit(port_idx, &smcibdev->port_event_mask);
                schedule_work(&smcibdev->port_event_work);
                break;
index a6d3623..4fd60c5 100644 (file)
@@ -166,7 +166,8 @@ static int smc_llc_add_pending_send(struct smc_link *link,
 {
        int rc;
 
-       rc = smc_wr_tx_get_free_slot(link, smc_llc_tx_handler, wr_buf, pend);
+       rc = smc_wr_tx_get_free_slot(link, smc_llc_tx_handler, wr_buf, NULL,
+                                    pend);
        if (rc < 0)
                return rc;
        BUILD_BUG_ON_MSG(
index 7cb3e4f..632c310 100644 (file)
@@ -27,7 +27,7 @@
 static struct nla_policy smc_pnet_policy[SMC_PNETID_MAX + 1] = {
        [SMC_PNETID_NAME] = {
                .type = NLA_NUL_STRING,
-               .len = SMC_MAX_PNETID_LEN - 1
+               .len = SMC_MAX_PNETID_LEN
        },
        [SMC_PNETID_ETHNAME] = {
                .type = NLA_NUL_STRING,
index d8366ed..f93f358 100644 (file)
@@ -165,12 +165,11 @@ int smc_tx_sendmsg(struct smc_sock *smc, struct msghdr *msg, size_t len)
                        conn->local_tx_ctrl.prod_flags.urg_data_pending = 1;
 
                if (!atomic_read(&conn->sndbuf_space) || conn->urg_tx_pend) {
+                       if (send_done)
+                               return send_done;
                        rc = smc_tx_wait(smc, msg->msg_flags);
-                       if (rc) {
-                               if (send_done)
-                                       return send_done;
+                       if (rc)
                                goto out_err;
-                       }
                        continue;
                }
 
@@ -267,27 +266,23 @@ int smcd_tx_ism_write(struct smc_connection *conn, void *data, size_t len,
 
 /* sndbuf consumer: actual data transfer of one target chunk with RDMA write */
 static int smc_tx_rdma_write(struct smc_connection *conn, int peer_rmbe_offset,
-                            int num_sges, struct ib_sge sges[])
+                            int num_sges, struct ib_rdma_wr *rdma_wr)
 {
        struct smc_link_group *lgr = conn->lgr;
-       struct ib_rdma_wr rdma_wr;
        struct smc_link *link;
        int rc;
 
-       memset(&rdma_wr, 0, sizeof(rdma_wr));
        link = &lgr->lnk[SMC_SINGLE_LINK];
-       rdma_wr.wr.wr_id = smc_wr_tx_get_next_wr_id(link);
-       rdma_wr.wr.sg_list = sges;
-       rdma_wr.wr.num_sge = num_sges;
-       rdma_wr.wr.opcode = IB_WR_RDMA_WRITE;
-       rdma_wr.remote_addr =
+       rdma_wr->wr.wr_id = smc_wr_tx_get_next_wr_id(link);
+       rdma_wr->wr.num_sge = num_sges;
+       rdma_wr->remote_addr =
                lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].dma_addr +
                /* RMBE within RMB */
                conn->tx_off +
                /* offset within RMBE */
                peer_rmbe_offset;
-       rdma_wr.rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey;
-       rc = ib_post_send(link->roce_qp, &rdma_wr.wr, NULL);
+       rdma_wr->rkey = lgr->rtokens[conn->rtoken_idx][SMC_SINGLE_LINK].rkey;
+       rc = ib_post_send(link->roce_qp, &rdma_wr->wr, NULL);
        if (rc) {
                conn->local_tx_ctrl.conn_state_flags.peer_conn_abort = 1;
                smc_lgr_terminate(lgr);
@@ -314,24 +309,25 @@ static inline void smc_tx_advance_cursors(struct smc_connection *conn,
 /* SMC-R helper for smc_tx_rdma_writes() */
 static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len,
                               size_t src_off, size_t src_len,
-                              size_t dst_off, size_t dst_len)
+                              size_t dst_off, size_t dst_len,
+                              struct smc_rdma_wr *wr_rdma_buf)
 {
        dma_addr_t dma_addr =
                sg_dma_address(conn->sndbuf_desc->sgt[SMC_SINGLE_LINK].sgl);
-       struct smc_link *link = &conn->lgr->lnk[SMC_SINGLE_LINK];
        int src_len_sum = src_len, dst_len_sum = dst_len;
-       struct ib_sge sges[SMC_IB_MAX_SEND_SGE];
        int sent_count = src_off;
        int srcchunk, dstchunk;
        int num_sges;
        int rc;
 
        for (dstchunk = 0; dstchunk < 2; dstchunk++) {
+               struct ib_sge *sge =
+                       wr_rdma_buf->wr_tx_rdma[dstchunk].wr.sg_list;
+
                num_sges = 0;
                for (srcchunk = 0; srcchunk < 2; srcchunk++) {
-                       sges[srcchunk].addr = dma_addr + src_off;
-                       sges[srcchunk].length = src_len;
-                       sges[srcchunk].lkey = link->roce_pd->local_dma_lkey;
+                       sge[srcchunk].addr = dma_addr + src_off;
+                       sge[srcchunk].length = src_len;
                        num_sges++;
 
                        src_off += src_len;
@@ -344,7 +340,8 @@ static int smcr_tx_rdma_writes(struct smc_connection *conn, size_t len,
                        src_len = dst_len - src_len; /* remainder */
                        src_len_sum += src_len;
                }
-               rc = smc_tx_rdma_write(conn, dst_off, num_sges, sges);
+               rc = smc_tx_rdma_write(conn, dst_off, num_sges,
+                                      &wr_rdma_buf->wr_tx_rdma[dstchunk]);
                if (rc)
                        return rc;
                if (dst_len_sum == len)
@@ -403,7 +400,8 @@ static int smcd_tx_rdma_writes(struct smc_connection *conn, size_t len,
 /* sndbuf consumer: prepare all necessary (src&dst) chunks of data transmit;
  * usable snd_wnd as max transmit
  */
-static int smc_tx_rdma_writes(struct smc_connection *conn)
+static int smc_tx_rdma_writes(struct smc_connection *conn,
+                             struct smc_rdma_wr *wr_rdma_buf)
 {
        size_t len, src_len, dst_off, dst_len; /* current chunk values */
        union smc_host_cursor sent, prep, prod, cons;
@@ -464,7 +462,7 @@ static int smc_tx_rdma_writes(struct smc_connection *conn)
                                         dst_off, dst_len);
        else
                rc = smcr_tx_rdma_writes(conn, len, sent.count, src_len,
-                                        dst_off, dst_len);
+                                        dst_off, dst_len, wr_rdma_buf);
        if (rc)
                return rc;
 
@@ -485,31 +483,30 @@ static int smc_tx_rdma_writes(struct smc_connection *conn)
 static int smcr_tx_sndbuf_nonempty(struct smc_connection *conn)
 {
        struct smc_cdc_producer_flags *pflags;
+       struct smc_rdma_wr *wr_rdma_buf;
        struct smc_cdc_tx_pend *pend;
        struct smc_wr_buf *wr_buf;
        int rc;
 
-       spin_lock_bh(&conn->send_lock);
-       rc = smc_cdc_get_free_slot(conn, &wr_buf, &pend);
+       rc = smc_cdc_get_free_slot(conn, &wr_buf, &wr_rdma_buf, &pend);
        if (rc < 0) {
                if (rc == -EBUSY) {
                        struct smc_sock *smc =
                                container_of(conn, struct smc_sock, conn);
 
-                       if (smc->sk.sk_err == ECONNABORTED) {
-                               rc = sock_error(&smc->sk);
-                               goto out_unlock;
-                       }
+                       if (smc->sk.sk_err == ECONNABORTED)
+                               return sock_error(&smc->sk);
                        rc = 0;
                        if (conn->alert_token_local) /* connection healthy */
                                mod_delayed_work(system_wq, &conn->tx_work,
                                                 SMC_TX_WORK_DELAY);
                }
-               goto out_unlock;
+               return rc;
        }
 
+       spin_lock_bh(&conn->send_lock);
        if (!conn->local_tx_ctrl.prod_flags.urg_data_present) {
-               rc = smc_tx_rdma_writes(conn);
+               rc = smc_tx_rdma_writes(conn, wr_rdma_buf);
                if (rc) {
                        smc_wr_tx_put_slot(&conn->lgr->lnk[SMC_SINGLE_LINK],
                                           (struct smc_wr_tx_pend_priv *)pend);
@@ -536,7 +533,7 @@ static int smcd_tx_sndbuf_nonempty(struct smc_connection *conn)
 
        spin_lock_bh(&conn->send_lock);
        if (!pflags->urg_data_present)
-               rc = smc_tx_rdma_writes(conn);
+               rc = smc_tx_rdma_writes(conn, NULL);
        if (!rc)
                rc = smcd_cdc_msg_send(conn);
 
@@ -598,7 +595,8 @@ void smc_tx_consumer_update(struct smc_connection *conn, bool force)
        if (to_confirm > conn->rmbe_update_limit) {
                smc_curs_copy(&prod, &conn->local_rx_ctrl.prod, conn);
                sender_free = conn->rmb_desc->len -
-                             smc_curs_diff(conn->rmb_desc->len, &prod, &cfed);
+                             smc_curs_diff_large(conn->rmb_desc->len,
+                                                 &cfed, &prod);
        }
 
        if (conn->local_rx_ctrl.prod_flags.cons_curs_upd_req ||
index c269475..253aa75 100644 (file)
@@ -160,6 +160,7 @@ static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx)
  * @link:              Pointer to smc_link used to later send the message.
  * @handler:           Send completion handler function pointer.
  * @wr_buf:            Out value returns pointer to message buffer.
+ * @wr_rdma_buf:       Out value returns pointer to rdma work request.
  * @wr_pend_priv:      Out value returns pointer serving as handler context.
  *
  * Return: 0 on success, or -errno on error.
@@ -167,6 +168,7 @@ static inline int smc_wr_tx_get_free_slot_index(struct smc_link *link, u32 *idx)
 int smc_wr_tx_get_free_slot(struct smc_link *link,
                            smc_wr_tx_handler handler,
                            struct smc_wr_buf **wr_buf,
+                           struct smc_rdma_wr **wr_rdma_buf,
                            struct smc_wr_tx_pend_priv **wr_pend_priv)
 {
        struct smc_wr_tx_pend *wr_pend;
@@ -204,6 +206,8 @@ int smc_wr_tx_get_free_slot(struct smc_link *link,
        wr_ib = &link->wr_tx_ibs[idx];
        wr_ib->wr_id = wr_id;
        *wr_buf = &link->wr_tx_bufs[idx];
+       if (wr_rdma_buf)
+               *wr_rdma_buf = &link->wr_tx_rdmas[idx];
        *wr_pend_priv = &wr_pend->priv;
        return 0;
 }
@@ -218,10 +222,10 @@ int smc_wr_tx_put_slot(struct smc_link *link,
                u32 idx = pend->idx;
 
                /* clear the full struct smc_wr_tx_pend including .priv */
-               memset(&link->wr_tx_pends[pend->idx], 0,
-                      sizeof(link->wr_tx_pends[pend->idx]));
-               memset(&link->wr_tx_bufs[pend->idx], 0,
-                      sizeof(link->wr_tx_bufs[pend->idx]));
+               memset(&link->wr_tx_pends[idx], 0,
+                      sizeof(link->wr_tx_pends[idx]));
+               memset(&link->wr_tx_bufs[idx], 0,
+                      sizeof(link->wr_tx_bufs[idx]));
                test_and_clear_bit(idx, link->wr_tx_mask);
                return 1;
        }
@@ -465,12 +469,26 @@ static void smc_wr_init_sge(struct smc_link *lnk)
                        lnk->wr_tx_dma_addr + i * SMC_WR_BUF_SIZE;
                lnk->wr_tx_sges[i].length = SMC_WR_TX_SIZE;
                lnk->wr_tx_sges[i].lkey = lnk->roce_pd->local_dma_lkey;
+               lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge[0].lkey =
+                       lnk->roce_pd->local_dma_lkey;
+               lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge[1].lkey =
+                       lnk->roce_pd->local_dma_lkey;
+               lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge[0].lkey =
+                       lnk->roce_pd->local_dma_lkey;
+               lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge[1].lkey =
+                       lnk->roce_pd->local_dma_lkey;
                lnk->wr_tx_ibs[i].next = NULL;
                lnk->wr_tx_ibs[i].sg_list = &lnk->wr_tx_sges[i];
                lnk->wr_tx_ibs[i].num_sge = 1;
                lnk->wr_tx_ibs[i].opcode = IB_WR_SEND;
                lnk->wr_tx_ibs[i].send_flags =
                        IB_SEND_SIGNALED | IB_SEND_SOLICITED;
+               lnk->wr_tx_rdmas[i].wr_tx_rdma[0].wr.opcode = IB_WR_RDMA_WRITE;
+               lnk->wr_tx_rdmas[i].wr_tx_rdma[1].wr.opcode = IB_WR_RDMA_WRITE;
+               lnk->wr_tx_rdmas[i].wr_tx_rdma[0].wr.sg_list =
+                       lnk->wr_tx_rdma_sges[i].tx_rdma_sge[0].wr_tx_rdma_sge;
+               lnk->wr_tx_rdmas[i].wr_tx_rdma[1].wr.sg_list =
+                       lnk->wr_tx_rdma_sges[i].tx_rdma_sge[1].wr_tx_rdma_sge;
        }
        for (i = 0; i < lnk->wr_rx_cnt; i++) {
                lnk->wr_rx_sges[i].addr =
@@ -521,8 +539,12 @@ void smc_wr_free_link_mem(struct smc_link *lnk)
        lnk->wr_tx_mask = NULL;
        kfree(lnk->wr_tx_sges);
        lnk->wr_tx_sges = NULL;
+       kfree(lnk->wr_tx_rdma_sges);
+       lnk->wr_tx_rdma_sges = NULL;
        kfree(lnk->wr_rx_sges);
        lnk->wr_rx_sges = NULL;
+       kfree(lnk->wr_tx_rdmas);
+       lnk->wr_tx_rdmas = NULL;
        kfree(lnk->wr_rx_ibs);
        lnk->wr_rx_ibs = NULL;
        kfree(lnk->wr_tx_ibs);
@@ -552,10 +574,20 @@ int smc_wr_alloc_link_mem(struct smc_link *link)
                                  GFP_KERNEL);
        if (!link->wr_rx_ibs)
                goto no_mem_wr_tx_ibs;
+       link->wr_tx_rdmas = kcalloc(SMC_WR_BUF_CNT,
+                                   sizeof(link->wr_tx_rdmas[0]),
+                                   GFP_KERNEL);
+       if (!link->wr_tx_rdmas)
+               goto no_mem_wr_rx_ibs;
+       link->wr_tx_rdma_sges = kcalloc(SMC_WR_BUF_CNT,
+                                       sizeof(link->wr_tx_rdma_sges[0]),
+                                       GFP_KERNEL);
+       if (!link->wr_tx_rdma_sges)
+               goto no_mem_wr_tx_rdmas;
        link->wr_tx_sges = kcalloc(SMC_WR_BUF_CNT, sizeof(link->wr_tx_sges[0]),
                                   GFP_KERNEL);
        if (!link->wr_tx_sges)
-               goto no_mem_wr_rx_ibs;
+               goto no_mem_wr_tx_rdma_sges;
        link->wr_rx_sges = kcalloc(SMC_WR_BUF_CNT * 3,
                                   sizeof(link->wr_rx_sges[0]),
                                   GFP_KERNEL);
@@ -579,6 +611,10 @@ no_mem_wr_rx_sges:
        kfree(link->wr_rx_sges);
 no_mem_wr_tx_sges:
        kfree(link->wr_tx_sges);
+no_mem_wr_tx_rdma_sges:
+       kfree(link->wr_tx_rdma_sges);
+no_mem_wr_tx_rdmas:
+       kfree(link->wr_tx_rdmas);
 no_mem_wr_rx_ibs:
        kfree(link->wr_rx_ibs);
 no_mem_wr_tx_ibs:
index 1d85bb1..09bf32f 100644 (file)
@@ -85,6 +85,7 @@ void smc_wr_add_dev(struct smc_ib_device *smcibdev);
 
 int smc_wr_tx_get_free_slot(struct smc_link *link, smc_wr_tx_handler handler,
                            struct smc_wr_buf **wr_buf,
+                           struct smc_rdma_wr **wrs,
                            struct smc_wr_tx_pend_priv **wr_pend_priv);
 int smc_wr_tx_put_slot(struct smc_link *link,
                       struct smc_wr_tx_pend_priv *wr_pend_priv);
index e89884e..d80d87a 100644 (file)
@@ -941,8 +941,7 @@ void dlci_ioctl_set(int (*hook) (unsigned int, void __user *))
 EXPORT_SYMBOL(dlci_ioctl_set);
 
 static long sock_do_ioctl(struct net *net, struct socket *sock,
-                         unsigned int cmd, unsigned long arg,
-                         unsigned int ifreq_size)
+                         unsigned int cmd, unsigned long arg)
 {
        int err;
        void __user *argp = (void __user *)arg;
@@ -968,11 +967,11 @@ static long sock_do_ioctl(struct net *net, struct socket *sock,
        } else {
                struct ifreq ifr;
                bool need_copyout;
-               if (copy_from_user(&ifr, argp, ifreq_size))
+               if (copy_from_user(&ifr, argp, sizeof(struct ifreq)))
                        return -EFAULT;
                err = dev_ioctl(net, cmd, &ifr, &need_copyout);
                if (!err && need_copyout)
-                       if (copy_to_user(argp, &ifr, ifreq_size))
+                       if (copy_to_user(argp, &ifr, sizeof(struct ifreq)))
                                return -EFAULT;
        }
        return err;
@@ -1071,8 +1070,7 @@ static long sock_ioctl(struct file *file, unsigned cmd, unsigned long arg)
                        err = open_related_ns(&net->ns, get_net_ns);
                        break;
                default:
-                       err = sock_do_ioctl(net, sock, cmd, arg,
-                                           sizeof(struct ifreq));
+                       err = sock_do_ioctl(net, sock, cmd, arg);
                        break;
                }
        return err;
@@ -2780,8 +2778,7 @@ static int do_siocgstamp(struct net *net, struct socket *sock,
        int err;
 
        set_fs(KERNEL_DS);
-       err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv,
-                           sizeof(struct compat_ifreq));
+       err = sock_do_ioctl(net, sock, cmd, (unsigned long)&ktv);
        set_fs(old_fs);
        if (!err)
                err = compat_put_timeval(&ktv, up);
@@ -2797,8 +2794,7 @@ static int do_siocgstampns(struct net *net, struct socket *sock,
        int err;
 
        set_fs(KERNEL_DS);
-       err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts,
-                           sizeof(struct compat_ifreq));
+       err = sock_do_ioctl(net, sock, cmd, (unsigned long)&kts);
        set_fs(old_fs);
        if (!err)
                err = compat_put_timespec(&kts, up);
@@ -2994,6 +2990,54 @@ static int compat_ifr_data_ioctl(struct net *net, unsigned int cmd,
        return dev_ioctl(net, cmd, &ifreq, NULL);
 }
 
+static int compat_ifreq_ioctl(struct net *net, struct socket *sock,
+                             unsigned int cmd,
+                             struct compat_ifreq __user *uifr32)
+{
+       struct ifreq __user *uifr;
+       int err;
+
+       /* Handle the fact that while struct ifreq has the same *layout* on
+        * 32/64 for everything but ifreq::ifru_ifmap and ifreq::ifru_data,
+        * which are handled elsewhere, it still has different *size* due to
+        * ifreq::ifru_ifmap (which is 16 bytes on 32 bit, 24 bytes on 64-bit,
+        * resulting in struct ifreq being 32 and 40 bytes respectively).
+        * As a result, if the struct happens to be at the end of a page and
+        * the next page isn't readable/writable, we get a fault. To prevent
+        * that, copy back and forth to the full size.
+        */
+
+       uifr = compat_alloc_user_space(sizeof(*uifr));
+       if (copy_in_user(uifr, uifr32, sizeof(*uifr32)))
+               return -EFAULT;
+
+       err = sock_do_ioctl(net, sock, cmd, (unsigned long)uifr);
+
+       if (!err) {
+               switch (cmd) {
+               case SIOCGIFFLAGS:
+               case SIOCGIFMETRIC:
+               case SIOCGIFMTU:
+               case SIOCGIFMEM:
+               case SIOCGIFHWADDR:
+               case SIOCGIFINDEX:
+               case SIOCGIFADDR:
+               case SIOCGIFBRDADDR:
+               case SIOCGIFDSTADDR:
+               case SIOCGIFNETMASK:
+               case SIOCGIFPFLAGS:
+               case SIOCGIFTXQLEN:
+               case SIOCGMIIPHY:
+               case SIOCGMIIREG:
+               case SIOCGIFNAME:
+                       if (copy_in_user(uifr32, uifr, sizeof(*uifr32)))
+                               err = -EFAULT;
+                       break;
+               }
+       }
+       return err;
+}
+
 static int compat_sioc_ifmap(struct net *net, unsigned int cmd,
                        struct compat_ifreq __user *uifr32)
 {
@@ -3109,8 +3153,7 @@ static int routing_ioctl(struct net *net, struct socket *sock,
        }
 
        set_fs(KERNEL_DS);
-       ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r,
-                           sizeof(struct compat_ifreq));
+       ret = sock_do_ioctl(net, sock, cmd, (unsigned long) r);
        set_fs(old_fs);
 
 out:
@@ -3210,21 +3253,22 @@ static int compat_sock_ioctl_trans(struct file *file, struct socket *sock,
        case SIOCSIFTXQLEN:
        case SIOCBRADDIF:
        case SIOCBRDELIF:
+       case SIOCGIFNAME:
        case SIOCSIFNAME:
        case SIOCGMIIPHY:
        case SIOCGMIIREG:
        case SIOCSMIIREG:
-       case SIOCSARP:
-       case SIOCGARP:
-       case SIOCDARP:
-       case SIOCATMARK:
        case SIOCBONDENSLAVE:
        case SIOCBONDRELEASE:
        case SIOCBONDSETHWADDR:
        case SIOCBONDCHANGEACTIVE:
-       case SIOCGIFNAME:
-               return sock_do_ioctl(net, sock, cmd, arg,
-                                    sizeof(struct compat_ifreq));
+               return compat_ifreq_ioctl(net, sock, cmd, argp);
+
+       case SIOCSARP:
+       case SIOCGARP:
+       case SIOCDARP:
+       case SIOCATMARK:
+               return sock_do_ioctl(net, sock, cmd, arg);
        }
 
        return -ENOIOCTLCMD;
index 1ff9768..f3023bb 100644 (file)
@@ -41,6 +41,9 @@ static unsigned long number_cred_unused;
 
 static struct cred machine_cred = {
        .usage = ATOMIC_INIT(1),
+#ifdef CONFIG_DEBUG_CREDENTIALS
+       .magic = CRED_MAGIC,
+#endif
 };
 
 /*
index dc86713..1531b02 100644 (file)
@@ -1549,8 +1549,10 @@ gss_marshal(struct rpc_task *task, __be32 *p)
        cred_len = p++;
 
        spin_lock(&ctx->gc_seq_lock);
-       req->rq_seqno = ctx->gc_seq++;
+       req->rq_seqno = (ctx->gc_seq < MAXSEQ) ? ctx->gc_seq++ : MAXSEQ;
        spin_unlock(&ctx->gc_seq_lock);
+       if (req->rq_seqno == MAXSEQ)
+               goto out_expired;
 
        *p++ = htonl((u32) RPC_GSS_VERSION);
        *p++ = htonl((u32) ctx->gc_proc);
@@ -1572,14 +1574,18 @@ gss_marshal(struct rpc_task *task, __be32 *p)
        mic.data = (u8 *)(p + 1);
        maj_stat = gss_get_mic(ctx->gc_gss_ctx, &verf_buf, &mic);
        if (maj_stat == GSS_S_CONTEXT_EXPIRED) {
-               clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+               goto out_expired;
        } else if (maj_stat != 0) {
-               printk("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
+               pr_warn("gss_marshal: gss_get_mic FAILED (%d)\n", maj_stat);
+               task->tk_status = -EIO;
                goto out_put_ctx;
        }
        p = xdr_encode_opaque(p, NULL, mic.len);
        gss_put_ctx(ctx);
        return p;
+out_expired:
+       clear_bit(RPCAUTH_CRED_UPTODATE, &cred->cr_flags);
+       task->tk_status = -EKEYEXPIRED;
 out_put_ctx:
        gss_put_ctx(ctx);
        return NULL;
index fb66562..5071051 100644 (file)
@@ -44,7 +44,7 @@ krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum,
                      unsigned char *cksum, unsigned char *buf)
 {
        struct crypto_sync_skcipher *cipher;
-       unsigned char plain[8];
+       unsigned char *plain;
        s32 code;
 
        dprintk("RPC:       %s:\n", __func__);
@@ -52,6 +52,10 @@ krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum,
        if (IS_ERR(cipher))
                return PTR_ERR(cipher);
 
+       plain = kmalloc(8, GFP_NOFS);
+       if (!plain)
+               return -ENOMEM;
+
        plain[0] = (unsigned char) ((seqnum >> 24) & 0xff);
        plain[1] = (unsigned char) ((seqnum >> 16) & 0xff);
        plain[2] = (unsigned char) ((seqnum >> 8) & 0xff);
@@ -67,6 +71,7 @@ krb5_make_rc4_seq_num(struct krb5_ctx *kctx, int direction, s32 seqnum,
 
        code = krb5_encrypt(cipher, cksum, plain, buf, 8);
 out:
+       kfree(plain);
        crypto_free_sync_skcipher(cipher);
        return code;
 }
@@ -77,12 +82,17 @@ krb5_make_seq_num(struct krb5_ctx *kctx,
                u32 seqnum,
                unsigned char *cksum, unsigned char *buf)
 {
-       unsigned char plain[8];
+       unsigned char *plain;
+       s32 code;
 
        if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC)
                return krb5_make_rc4_seq_num(kctx, direction, seqnum,
                                             cksum, buf);
 
+       plain = kmalloc(8, GFP_NOFS);
+       if (!plain)
+               return -ENOMEM;
+
        plain[0] = (unsigned char) (seqnum & 0xff);
        plain[1] = (unsigned char) ((seqnum >> 8) & 0xff);
        plain[2] = (unsigned char) ((seqnum >> 16) & 0xff);
@@ -93,7 +103,9 @@ krb5_make_seq_num(struct krb5_ctx *kctx,
        plain[6] = direction;
        plain[7] = direction;
 
-       return krb5_encrypt(key, cksum, plain, buf, 8);
+       code = krb5_encrypt(key, cksum, plain, buf, 8);
+       kfree(plain);
+       return code;
 }
 
 static s32
@@ -101,7 +113,7 @@ krb5_get_rc4_seq_num(struct krb5_ctx *kctx, unsigned char *cksum,
                     unsigned char *buf, int *direction, s32 *seqnum)
 {
        struct crypto_sync_skcipher *cipher;
-       unsigned char plain[8];
+       unsigned char *plain;
        s32 code;
 
        dprintk("RPC:       %s:\n", __func__);
@@ -113,20 +125,28 @@ krb5_get_rc4_seq_num(struct krb5_ctx *kctx, unsigned char *cksum,
        if (code)
                goto out;
 
+       plain = kmalloc(8, GFP_NOFS);
+       if (!plain) {
+               code = -ENOMEM;
+               goto out;
+       }
+
        code = krb5_decrypt(cipher, cksum, buf, plain, 8);
        if (code)
-               goto out;
+               goto out_plain;
 
        if ((plain[4] != plain[5]) || (plain[4] != plain[6])
                                   || (plain[4] != plain[7])) {
                code = (s32)KG_BAD_SEQ;
-               goto out;
+               goto out_plain;
        }
 
        *direction = plain[4];
 
        *seqnum = ((plain[0] << 24) | (plain[1] << 16) |
                                        (plain[2] << 8) | (plain[3]));
+out_plain:
+       kfree(plain);
 out:
        crypto_free_sync_skcipher(cipher);
        return code;
@@ -139,7 +159,7 @@ krb5_get_seq_num(struct krb5_ctx *kctx,
               int *direction, u32 *seqnum)
 {
        s32 code;
-       unsigned char plain[8];
+       unsigned char *plain;
        struct crypto_sync_skcipher *key = kctx->seq;
 
        dprintk("RPC:       krb5_get_seq_num:\n");
@@ -147,18 +167,25 @@ krb5_get_seq_num(struct krb5_ctx *kctx,
        if (kctx->enctype == ENCTYPE_ARCFOUR_HMAC)
                return krb5_get_rc4_seq_num(kctx, cksum, buf,
                                            direction, seqnum);
+       plain = kmalloc(8, GFP_NOFS);
+       if (!plain)
+               return -ENOMEM;
 
        if ((code = krb5_decrypt(key, cksum, buf, plain, 8)))
-               return code;
+               goto out;
 
        if ((plain[4] != plain[5]) || (plain[4] != plain[6]) ||
-           (plain[4] != plain[7]))
-               return (s32)KG_BAD_SEQ;
+           (plain[4] != plain[7])) {
+               code = (s32)KG_BAD_SEQ;
+               goto out;
+       }
 
        *direction = plain[4];
 
        *seqnum = ((plain[0]) |
                   (plain[1] << 8) | (plain[2] << 16) | (plain[3] << 24));
 
-       return 0;
+out:
+       kfree(plain);
+       return code;
 }
index 71d9599..d7ec613 100644 (file)
@@ -1739,14 +1739,10 @@ rpc_xdr_encode(struct rpc_task *task)
        xdr_buf_init(&req->rq_rcv_buf,
                     req->rq_rbuffer,
                     req->rq_rcvsize);
-       req->rq_bytes_sent = 0;
 
        p = rpc_encode_header(task);
-       if (p == NULL) {
-               printk(KERN_INFO "RPC: couldn't encode RPC header, exit EIO\n");
-               rpc_exit(task, -EIO);
+       if (p == NULL)
                return;
-       }
 
        encode = task->tk_msg.rpc_proc->p_encode;
        if (encode == NULL)
@@ -1771,10 +1767,17 @@ call_encode(struct rpc_task *task)
        /* Did the encode result in an error condition? */
        if (task->tk_status != 0) {
                /* Was the error nonfatal? */
-               if (task->tk_status == -EAGAIN || task->tk_status == -ENOMEM)
+               switch (task->tk_status) {
+               case -EAGAIN:
+               case -ENOMEM:
                        rpc_delay(task, HZ >> 4);
-               else
+                       break;
+               case -EKEYEXPIRED:
+                       task->tk_action = call_refresh;
+                       break;
+               default:
                        rpc_exit(task, task->tk_status);
+               }
                return;
        }
 
@@ -2336,7 +2339,8 @@ rpc_encode_header(struct rpc_task *task)
        *p++ = htonl(clnt->cl_vers);    /* program version */
        *p++ = htonl(task->tk_msg.rpc_proc->p_proc);    /* procedure */
        p = rpcauth_marshcred(task, p);
-       req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p);
+       if (p)
+               req->rq_slen = xdr_adjust_iovec(&req->rq_svec[0], p);
        return p;
 }
 
index 45a0333..19bb356 100644 (file)
@@ -146,7 +146,7 @@ rpc_clnt_debugfs_register(struct rpc_clnt *clnt)
        rcu_read_lock();
        xprt = rcu_dereference(clnt->cl_xprt);
        /* no "debugfs" dentry? Don't bother with the symlink. */
-       if (!xprt->debugfs) {
+       if (IS_ERR_OR_NULL(xprt->debugfs)) {
                rcu_read_unlock();
                return;
        }
index 73547d1..f1ec211 100644 (file)
@@ -1151,6 +1151,7 @@ xprt_request_enqueue_transmit(struct rpc_task *task)
        struct rpc_xprt *xprt = req->rq_xprt;
 
        if (xprt_request_need_enqueue_transmit(task, req)) {
+               req->rq_bytes_sent = 0;
                spin_lock(&xprt->queue_lock);
                /*
                 * Requests that carry congestion control credits are added
@@ -1177,7 +1178,7 @@ xprt_request_enqueue_transmit(struct rpc_task *task)
                                INIT_LIST_HEAD(&req->rq_xmit2);
                                goto out;
                        }
-               } else {
+               } else if (!req->rq_seqno) {
                        list_for_each_entry(pos, &xprt->xmit_queue, rq_xmit) {
                                if (pos->rq_task->tk_owner != task->tk_owner)
                                        continue;
index cf51b8f..1f20011 100644 (file)
@@ -537,6 +537,99 @@ void svc_rdma_sync_reply_hdr(struct svcxprt_rdma *rdma,
                                      DMA_TO_DEVICE);
 }
 
+/* If the xdr_buf has more elements than the device can
+ * transmit in a single RDMA Send, then the reply will
+ * have to be copied into a bounce buffer.
+ */
+static bool svc_rdma_pull_up_needed(struct svcxprt_rdma *rdma,
+                                   struct xdr_buf *xdr,
+                                   __be32 *wr_lst)
+{
+       int elements;
+
+       /* xdr->head */
+       elements = 1;
+
+       /* xdr->pages */
+       if (!wr_lst) {
+               unsigned int remaining;
+               unsigned long pageoff;
+
+               pageoff = xdr->page_base & ~PAGE_MASK;
+               remaining = xdr->page_len;
+               while (remaining) {
+                       ++elements;
+                       remaining -= min_t(u32, PAGE_SIZE - pageoff,
+                                          remaining);
+                       pageoff = 0;
+               }
+       }
+
+       /* xdr->tail */
+       if (xdr->tail[0].iov_len)
+               ++elements;
+
+       /* assume 1 SGE is needed for the transport header */
+       return elements >= rdma->sc_max_send_sges;
+}
+
+/* The device is not capable of sending the reply directly.
+ * Assemble the elements of @xdr into the transport header
+ * buffer.
+ */
+static int svc_rdma_pull_up_reply_msg(struct svcxprt_rdma *rdma,
+                                     struct svc_rdma_send_ctxt *ctxt,
+                                     struct xdr_buf *xdr, __be32 *wr_lst)
+{
+       unsigned char *dst, *tailbase;
+       unsigned int taillen;
+
+       dst = ctxt->sc_xprt_buf;
+       dst += ctxt->sc_sges[0].length;
+
+       memcpy(dst, xdr->head[0].iov_base, xdr->head[0].iov_len);
+       dst += xdr->head[0].iov_len;
+
+       tailbase = xdr->tail[0].iov_base;
+       taillen = xdr->tail[0].iov_len;
+       if (wr_lst) {
+               u32 xdrpad;
+
+               xdrpad = xdr_padsize(xdr->page_len);
+               if (taillen && xdrpad) {
+                       tailbase += xdrpad;
+                       taillen -= xdrpad;
+               }
+       } else {
+               unsigned int len, remaining;
+               unsigned long pageoff;
+               struct page **ppages;
+
+               ppages = xdr->pages + (xdr->page_base >> PAGE_SHIFT);
+               pageoff = xdr->page_base & ~PAGE_MASK;
+               remaining = xdr->page_len;
+               while (remaining) {
+                       len = min_t(u32, PAGE_SIZE - pageoff, remaining);
+
+                       memcpy(dst, page_address(*ppages), len);
+                       remaining -= len;
+                       dst += len;
+                       pageoff = 0;
+               }
+       }
+
+       if (taillen)
+               memcpy(dst, tailbase, taillen);
+
+       ctxt->sc_sges[0].length += xdr->len;
+       ib_dma_sync_single_for_device(rdma->sc_pd->device,
+                                     ctxt->sc_sges[0].addr,
+                                     ctxt->sc_sges[0].length,
+                                     DMA_TO_DEVICE);
+
+       return 0;
+}
+
 /* svc_rdma_map_reply_msg - Map the buffer holding RPC message
  * @rdma: controlling transport
  * @ctxt: send_ctxt for the Send WR
@@ -559,8 +652,10 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
        u32 xdr_pad;
        int ret;
 
-       if (++ctxt->sc_cur_sge_no >= rdma->sc_max_send_sges)
-               return -EIO;
+       if (svc_rdma_pull_up_needed(rdma, xdr, wr_lst))
+               return svc_rdma_pull_up_reply_msg(rdma, ctxt, xdr, wr_lst);
+
+       ++ctxt->sc_cur_sge_no;
        ret = svc_rdma_dma_map_buf(rdma, ctxt,
                                   xdr->head[0].iov_base,
                                   xdr->head[0].iov_len);
@@ -591,8 +686,7 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
        while (remaining) {
                len = min_t(u32, PAGE_SIZE - page_off, remaining);
 
-               if (++ctxt->sc_cur_sge_no >= rdma->sc_max_send_sges)
-                       return -EIO;
+               ++ctxt->sc_cur_sge_no;
                ret = svc_rdma_dma_map_page(rdma, ctxt, *ppages++,
                                            page_off, len);
                if (ret < 0)
@@ -606,8 +700,7 @@ int svc_rdma_map_reply_msg(struct svcxprt_rdma *rdma,
        len = xdr->tail[0].iov_len;
 tail:
        if (len) {
-               if (++ctxt->sc_cur_sge_no >= rdma->sc_max_send_sges)
-                       return -EIO;
+               ++ctxt->sc_cur_sge_no;
                ret = svc_rdma_dma_map_buf(rdma, ctxt, base, len);
                if (ret < 0)
                        return ret;
index 924c17d..57f86c6 100644 (file)
@@ -419,12 +419,9 @@ static struct svc_xprt *svc_rdma_accept(struct svc_xprt *xprt)
        /* Transport header, head iovec, tail iovec */
        newxprt->sc_max_send_sges = 3;
        /* Add one SGE per page list entry */
-       newxprt->sc_max_send_sges += svcrdma_max_req_size / PAGE_SIZE;
-       if (newxprt->sc_max_send_sges > dev->attrs.max_send_sge) {
-               pr_err("svcrdma: too few Send SGEs available (%d needed)\n",
-                      newxprt->sc_max_send_sges);
-               goto errout;
-       }
+       newxprt->sc_max_send_sges += (svcrdma_max_req_size / PAGE_SIZE) + 1;
+       if (newxprt->sc_max_send_sges > dev->attrs.max_send_sge)
+               newxprt->sc_max_send_sges = dev->attrs.max_send_sge;
        newxprt->sc_max_req_size = svcrdma_max_req_size;
        newxprt->sc_max_requests = svcrdma_max_requests;
        newxprt->sc_max_bc_requests = svcrdma_max_bc_requests;
index 7749a2b..21113bf 100644 (file)
@@ -527,7 +527,8 @@ rpcrdma_ep_create(struct rpcrdma_ep *ep, struct rpcrdma_ia *ia,
 
        sendcq = ib_alloc_cq(ia->ri_device, NULL,
                             ep->rep_attr.cap.max_send_wr + 1,
-                            1, IB_POLL_WORKQUEUE);
+                            ia->ri_device->num_comp_vectors > 1 ? 1 : 0,
+                            IB_POLL_WORKQUEUE);
        if (IS_ERR(sendcq)) {
                rc = PTR_ERR(sendcq);
                goto out1;
@@ -845,17 +846,13 @@ static int rpcrdma_sendctxs_create(struct rpcrdma_xprt *r_xprt)
        for (i = 0; i <= buf->rb_sc_last; i++) {
                sc = rpcrdma_sendctx_create(&r_xprt->rx_ia);
                if (!sc)
-                       goto out_destroy;
+                       return -ENOMEM;
 
                sc->sc_xprt = r_xprt;
                buf->rb_sc_ctxs[i] = sc;
        }
 
        return 0;
-
-out_destroy:
-       rpcrdma_sendctxs_destroy(buf);
-       return -ENOMEM;
 }
 
 /* The sendctx queue is not guaranteed to have a size that is a
@@ -1113,8 +1110,10 @@ rpcrdma_buffer_create(struct rpcrdma_xprt *r_xprt)
                                                WQ_MEM_RECLAIM | WQ_HIGHPRI,
                                                0,
                        r_xprt->rx_xprt.address_strings[RPC_DISPLAY_ADDR]);
-       if (!buf->rb_completion_wq)
+       if (!buf->rb_completion_wq) {
+               rc = -ENOMEM;
                goto out;
+       }
 
        return 0;
 out:
index 13559e6..7754aa3 100644 (file)
@@ -48,6 +48,7 @@
 #include <net/udp.h>
 #include <net/tcp.h>
 #include <linux/bvec.h>
+#include <linux/highmem.h>
 #include <linux/uio.h>
 
 #include <trace/events/sunrpc.h>
@@ -376,6 +377,26 @@ xs_read_discard(struct socket *sock, struct msghdr *msg, int flags,
        return sock_recvmsg(sock, msg, flags);
 }
 
+#if ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE
+static void
+xs_flush_bvec(const struct bio_vec *bvec, size_t count, size_t seek)
+{
+       struct bvec_iter bi = {
+               .bi_size = count,
+       };
+       struct bio_vec bv;
+
+       bvec_iter_advance(bvec, &bi, seek & PAGE_MASK);
+       for_each_bvec(bv, bvec, bi, bi)
+               flush_dcache_page(bv.bv_page);
+}
+#else
+static inline void
+xs_flush_bvec(const struct bio_vec *bvec, size_t count, size_t seek)
+{
+}
+#endif
+
 static ssize_t
 xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
                struct xdr_buf *buf, size_t count, size_t seek, size_t *read)
@@ -409,6 +430,7 @@ xs_read_xdr_buf(struct socket *sock, struct msghdr *msg, int flags,
                                seek + buf->page_base);
                if (ret <= 0)
                        goto sock_err;
+               xs_flush_bvec(buf->bvec, ret, seek + buf->page_base);
                offset += ret - buf->page_base;
                if (offset == count || msg->msg_flags & (MSG_EOR|MSG_TRUNC))
                        goto out;
index 2792a3c..85ad5c0 100644 (file)
@@ -1145,7 +1145,7 @@ static bool tipc_data_input(struct tipc_link *l, struct sk_buff *skb,
        default:
                pr_warn("Dropping received illegal msg type\n");
                kfree_skb(skb);
-               return false;
+               return true;
        };
 }
 
@@ -1425,6 +1425,10 @@ static void tipc_link_build_proto_msg(struct tipc_link *l, int mtyp, bool probe,
                l->rcv_unacked = 0;
        } else {
                /* RESET_MSG or ACTIVATE_MSG */
+               if (mtyp == ACTIVATE_MSG) {
+                       msg_set_dest_session_valid(hdr, 1);
+                       msg_set_dest_session(hdr, l->peer_session);
+               }
                msg_set_max_pkt(hdr, l->advertised_mtu);
                strcpy(data, l->if_name);
                msg_set_size(hdr, INT_H_SIZE + TIPC_MAX_IF_NAME);
@@ -1642,6 +1646,17 @@ static int tipc_link_proto_rcv(struct tipc_link *l, struct sk_buff *skb,
                        rc = tipc_link_fsm_evt(l, LINK_FAILURE_EVT);
                        break;
                }
+
+               /* If this endpoint was re-created while peer was ESTABLISHING
+                * it doesn't know current session number. Force re-synch.
+                */
+               if (mtyp == ACTIVATE_MSG && msg_dest_session_valid(hdr) &&
+                   l->session != msg_dest_session(hdr)) {
+                       if (less(l->session, msg_dest_session(hdr)))
+                               l->session = msg_dest_session(hdr) + 1;
+                       break;
+               }
+
                /* ACTIVATE_MSG serves as PEER_RESET if link is already down */
                if (mtyp == RESET_MSG || !link_is_up(l))
                        rc = tipc_link_fsm_evt(l, LINK_PEER_RESET_EVT);
index a092495..d7e4b8b 100644 (file)
@@ -360,6 +360,28 @@ static inline void msg_set_bcast_ack(struct tipc_msg *m, u16 n)
        msg_set_bits(m, 1, 0, 0xffff, n);
 }
 
+/* Note: reusing bits in word 1 for ACTIVATE_MSG only, to re-synch
+ * link peer session number
+ */
+static inline bool msg_dest_session_valid(struct tipc_msg *m)
+{
+       return msg_bits(m, 1, 16, 0x1);
+}
+
+static inline void msg_set_dest_session_valid(struct tipc_msg *m, bool valid)
+{
+       msg_set_bits(m, 1, 16, 0x1, valid);
+}
+
+static inline u16 msg_dest_session(struct tipc_msg *m)
+{
+       return msg_bits(m, 1, 0, 0xffff);
+}
+
+static inline void msg_set_dest_session(struct tipc_msg *m, u16 n)
+{
+       msg_set_bits(m, 1, 0, 0xffff, n);
+}
 
 /*
  * Word 2
index 40f5cae..4ad3586 100644 (file)
@@ -87,6 +87,11 @@ static int tipc_skb_tailroom(struct sk_buff *skb)
        return limit;
 }
 
+static inline int TLV_GET_DATA_LEN(struct tlv_desc *tlv)
+{
+       return TLV_GET_LEN(tlv) - TLV_SPACE(0);
+}
+
 static int tipc_add_tlv(struct sk_buff *skb, u16 type, void *data, u16 len)
 {
        struct tlv_desc *tlv = (struct tlv_desc *)skb_tail_pointer(skb);
@@ -166,6 +171,11 @@ static struct sk_buff *tipc_get_err_tlv(char *str)
        return buf;
 }
 
+static inline bool string_is_valid(char *s, int len)
+{
+       return memchr(s, '\0', len) ? true : false;
+}
+
 static int __tipc_nl_compat_dumpit(struct tipc_nl_compat_cmd_dump *cmd,
                                   struct tipc_nl_compat_msg *msg,
                                   struct sk_buff *arg)
@@ -379,6 +389,7 @@ static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd,
        struct nlattr *prop;
        struct nlattr *bearer;
        struct tipc_bearer_config *b;
+       int len;
 
        b = (struct tipc_bearer_config *)TLV_DATA(msg->req);
 
@@ -386,6 +397,10 @@ static int tipc_nl_compat_bearer_enable(struct tipc_nl_compat_cmd_doit *cmd,
        if (!bearer)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_BEARER_NAME);
+       if (!string_is_valid(b->name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, b->name))
                return -EMSGSIZE;
 
@@ -411,6 +426,7 @@ static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd,
 {
        char *name;
        struct nlattr *bearer;
+       int len;
 
        name = (char *)TLV_DATA(msg->req);
 
@@ -418,6 +434,10 @@ static int tipc_nl_compat_bearer_disable(struct tipc_nl_compat_cmd_doit *cmd,
        if (!bearer)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_BEARER_NAME);
+       if (!string_is_valid(name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, name))
                return -EMSGSIZE;
 
@@ -478,6 +498,7 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg,
        struct nlattr *prop[TIPC_NLA_PROP_MAX + 1];
        struct nlattr *stats[TIPC_NLA_STATS_MAX + 1];
        int err;
+       int len;
 
        if (!attrs[TIPC_NLA_LINK])
                return -EINVAL;
@@ -504,6 +525,11 @@ static int tipc_nl_compat_link_stat_dump(struct tipc_nl_compat_msg *msg,
                return err;
 
        name = (char *)TLV_DATA(msg->req);
+
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
+       if (!string_is_valid(name, len))
+               return -EINVAL;
+
        if (strcmp(name, nla_data(link[TIPC_NLA_LINK_NAME])) != 0)
                return 0;
 
@@ -644,6 +670,7 @@ static int tipc_nl_compat_media_set(struct sk_buff *skb,
        struct nlattr *prop;
        struct nlattr *media;
        struct tipc_link_config *lc;
+       int len;
 
        lc = (struct tipc_link_config *)TLV_DATA(msg->req);
 
@@ -651,6 +678,10 @@ static int tipc_nl_compat_media_set(struct sk_buff *skb,
        if (!media)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_MEDIA_NAME);
+       if (!string_is_valid(lc->name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_MEDIA_NAME, lc->name))
                return -EMSGSIZE;
 
@@ -671,6 +702,7 @@ static int tipc_nl_compat_bearer_set(struct sk_buff *skb,
        struct nlattr *prop;
        struct nlattr *bearer;
        struct tipc_link_config *lc;
+       int len;
 
        lc = (struct tipc_link_config *)TLV_DATA(msg->req);
 
@@ -678,6 +710,10 @@ static int tipc_nl_compat_bearer_set(struct sk_buff *skb,
        if (!bearer)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_MEDIA_NAME);
+       if (!string_is_valid(lc->name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_BEARER_NAME, lc->name))
                return -EMSGSIZE;
 
@@ -726,9 +762,14 @@ static int tipc_nl_compat_link_set(struct tipc_nl_compat_cmd_doit *cmd,
        struct tipc_link_config *lc;
        struct tipc_bearer *bearer;
        struct tipc_media *media;
+       int len;
 
        lc = (struct tipc_link_config *)TLV_DATA(msg->req);
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
+       if (!string_is_valid(lc->name, len))
+               return -EINVAL;
+
        media = tipc_media_find(lc->name);
        if (media) {
                cmd->doit = &__tipc_nl_media_set;
@@ -750,6 +791,7 @@ static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd,
 {
        char *name;
        struct nlattr *link;
+       int len;
 
        name = (char *)TLV_DATA(msg->req);
 
@@ -757,6 +799,10 @@ static int tipc_nl_compat_link_reset_stats(struct tipc_nl_compat_cmd_doit *cmd,
        if (!link)
                return -EMSGSIZE;
 
+       len = min_t(int, TLV_GET_DATA_LEN(msg->req), TIPC_MAX_LINK_NAME);
+       if (!string_is_valid(name, len))
+               return -EINVAL;
+
        if (nla_put_string(skb, TIPC_NLA_LINK_NAME, name))
                return -EMSGSIZE;
 
@@ -778,6 +824,8 @@ static int tipc_nl_compat_name_table_dump_header(struct tipc_nl_compat_msg *msg)
        };
 
        ntq = (struct tipc_name_table_query *)TLV_DATA(msg->req);
+       if (TLV_GET_DATA_LEN(msg->req) < sizeof(struct tipc_name_table_query))
+               return -EINVAL;
 
        depth = ntohl(ntq->depth);
 
@@ -904,8 +952,10 @@ static int tipc_nl_compat_publ_dump(struct tipc_nl_compat_msg *msg, u32 sock)
 
        hdr = genlmsg_put(args, 0, 0, &tipc_genl_family, NLM_F_MULTI,
                          TIPC_NL_PUBL_GET);
-       if (!hdr)
+       if (!hdr) {
+               kfree_skb(args);
                return -EMSGSIZE;
+       }
 
        nest = nla_nest_start(args, TIPC_NLA_SOCK);
        if (!nest) {
@@ -1206,7 +1256,7 @@ static int tipc_nl_compat_recv(struct sk_buff *skb, struct genl_info *info)
        }
 
        len = nlmsg_attrlen(req_nlh, GENL_HDRLEN + TIPC_GENL_HDRLEN);
-       if (len && !TLV_OK(msg.req, len)) {
+       if (!len || !TLV_OK(msg.req, len)) {
                msg.rep = tipc_get_err_tlv(TIPC_CFG_NOT_SUPPORTED);
                err = -EOPNOTSUPP;
                goto send;
index db2a6c3..2dc4919 100644 (file)
@@ -830,15 +830,16 @@ static void tipc_node_link_down(struct tipc_node *n, int bearer_id, bool delete)
        tipc_node_write_lock(n);
        if (!tipc_link_is_establishing(l)) {
                __tipc_node_link_down(n, &bearer_id, &xmitq, &maddr);
-               if (delete) {
-                       kfree(l);
-                       le->link = NULL;
-                       n->link_cnt--;
-               }
        } else {
                /* Defuse pending tipc_node_link_up() */
+               tipc_link_reset(l);
                tipc_link_fsm_evt(l, LINK_RESET_EVT);
        }
+       if (delete) {
+               kfree(l);
+               le->link = NULL;
+               n->link_cnt--;
+       }
        trace_tipc_node_link_down(n, true, "node link down or deleted!");
        tipc_node_write_unlock(n);
        if (delete)
index 1217c90..684f212 100644 (file)
@@ -388,7 +388,7 @@ static int tipc_sk_sock_err(struct socket *sock, long *timeout)
                rc_ = tipc_sk_sock_err((sock_), timeo_);                       \
                if (rc_)                                                       \
                        break;                                                 \
-               prepare_to_wait(sk_sleep(sk_), &wait_, TASK_INTERRUPTIBLE);    \
+               add_wait_queue(sk_sleep(sk_), &wait_);                         \
                release_sock(sk_);                                             \
                *(timeo_) = wait_woken(&wait_, TASK_INTERRUPTIBLE, *(timeo_)); \
                sched_annotate_sleep();                                        \
@@ -1677,7 +1677,7 @@ static void tipc_sk_send_ack(struct tipc_sock *tsk)
 static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
 {
        struct sock *sk = sock->sk;
-       DEFINE_WAIT(wait);
+       DEFINE_WAIT_FUNC(wait, woken_wake_function);
        long timeo = *timeop;
        int err = sock_error(sk);
 
@@ -1685,15 +1685,17 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
                return err;
 
        for (;;) {
-               prepare_to_wait(sk_sleep(sk), &wait, TASK_INTERRUPTIBLE);
                if (timeo && skb_queue_empty(&sk->sk_receive_queue)) {
                        if (sk->sk_shutdown & RCV_SHUTDOWN) {
                                err = -ENOTCONN;
                                break;
                        }
+                       add_wait_queue(sk_sleep(sk), &wait);
                        release_sock(sk);
-                       timeo = schedule_timeout(timeo);
+                       timeo = wait_woken(&wait, TASK_INTERRUPTIBLE, timeo);
+                       sched_annotate_sleep();
                        lock_sock(sk);
+                       remove_wait_queue(sk_sleep(sk), &wait);
                }
                err = 0;
                if (!skb_queue_empty(&sk->sk_receive_queue))
@@ -1709,7 +1711,6 @@ static int tipc_wait_for_rcvmsg(struct socket *sock, long *timeop)
                if (err)
                        break;
        }
-       finish_wait(sk_sleep(sk), &wait);
        *timeop = timeo;
        return err;
 }
index efb16f6..a457c0f 100644 (file)
@@ -398,7 +398,7 @@ static int tipc_conn_rcv_from_sock(struct tipc_conn *con)
        ret = sock_recvmsg(con->sock, &msg, MSG_DONTWAIT);
        if (ret == -EWOULDBLOCK)
                return -EWOULDBLOCK;
-       if (ret > 0) {
+       if (ret == sizeof(s)) {
                read_lock_bh(&sk->sk_callback_lock);
                ret = tipc_conn_rcv_sub(srv, con, &s);
                read_unlock_bh(&sk->sk_callback_lock);
index 11cdc8f..bf5b54b 100644 (file)
@@ -439,6 +439,8 @@ static int tls_do_encryption(struct sock *sk,
        struct scatterlist *sge = sk_msg_elem(msg_en, start);
        int rc;
 
+       memcpy(rec->iv_data, tls_ctx->tx.iv, sizeof(rec->iv_data));
+
        sge->offset += tls_ctx->tx.prepend_size;
        sge->length -= tls_ctx->tx.prepend_size;
 
@@ -448,7 +450,7 @@ static int tls_do_encryption(struct sock *sk,
        aead_request_set_ad(aead_req, TLS_AAD_SPACE_SIZE);
        aead_request_set_crypt(aead_req, rec->sg_aead_in,
                               rec->sg_aead_out,
-                              data_len, tls_ctx->tx.iv);
+                              data_len, rec->iv_data);
 
        aead_request_set_callback(aead_req, CRYPTO_TFM_REQ_MAY_BACKLOG,
                                  tls_encrypt_done, sk);
@@ -1792,7 +1794,9 @@ void tls_sw_free_resources_tx(struct sock *sk)
        if (atomic_read(&ctx->encrypt_pending))
                crypto_wait_req(-EINPROGRESS, &ctx->async_wait);
 
+       release_sock(sk);
        cancel_delayed_work_sync(&ctx->tx_work.work);
+       lock_sock(sk);
 
        /* Tx whatever records we can transmit and abandon the rest */
        tls_tx_records(sk, -1);
index 74d1eed..a95d479 100644 (file)
@@ -890,7 +890,7 @@ retry:
        addr->hash ^= sk->sk_type;
 
        __unix_remove_socket(sk);
-       u->addr = addr;
+       smp_store_release(&u->addr, addr);
        __unix_insert_socket(&unix_socket_table[addr->hash], sk);
        spin_unlock(&unix_table_lock);
        err = 0;
@@ -1060,7 +1060,7 @@ static int unix_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
 
        err = 0;
        __unix_remove_socket(sk);
-       u->addr = addr;
+       smp_store_release(&u->addr, addr);
        __unix_insert_socket(list, sk);
 
 out_unlock:
@@ -1331,15 +1331,29 @@ restart:
        RCU_INIT_POINTER(newsk->sk_wq, &newu->peer_wq);
        otheru = unix_sk(other);
 
-       /* copy address information from listening to new sock*/
-       if (otheru->addr) {
-               refcount_inc(&otheru->addr->refcnt);
-               newu->addr = otheru->addr;
-       }
+       /* copy address information from listening to new sock
+        *
+        * The contents of *(otheru->addr) and otheru->path
+        * are seen fully set up here, since we have found
+        * otheru in hash under unix_table_lock.  Insertion
+        * into the hash chain we'd found it in had been done
+        * in an earlier critical area protected by unix_table_lock,
+        * the same one where we'd set *(otheru->addr) contents,
+        * as well as otheru->path and otheru->addr itself.
+        *
+        * Using smp_store_release() here to set newu->addr
+        * is enough to make those stores, as well as stores
+        * to newu->path visible to anyone who gets newu->addr
+        * by smp_load_acquire().  IOW, the same warranties
+        * as for unix_sock instances bound in unix_bind() or
+        * in unix_autobind().
+        */
        if (otheru->path.dentry) {
                path_get(&otheru->path);
                newu->path = otheru->path;
        }
+       refcount_inc(&otheru->addr->refcnt);
+       smp_store_release(&newu->addr, otheru->addr);
 
        /* Set credentials */
        copy_peercred(sk, other);
@@ -1453,7 +1467,7 @@ out:
 static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
 {
        struct sock *sk = sock->sk;
-       struct unix_sock *u;
+       struct unix_address *addr;
        DECLARE_SOCKADDR(struct sockaddr_un *, sunaddr, uaddr);
        int err = 0;
 
@@ -1468,19 +1482,15 @@ static int unix_getname(struct socket *sock, struct sockaddr *uaddr, int peer)
                sock_hold(sk);
        }
 
-       u = unix_sk(sk);
-       unix_state_lock(sk);
-       if (!u->addr) {
+       addr = smp_load_acquire(&unix_sk(sk)->addr);
+       if (!addr) {
                sunaddr->sun_family = AF_UNIX;
                sunaddr->sun_path[0] = 0;
                err = sizeof(short);
        } else {
-               struct unix_address *addr = u->addr;
-
                err = addr->len;
                memcpy(sunaddr, addr->name, addr->len);
        }
-       unix_state_unlock(sk);
        sock_put(sk);
 out:
        return err;
@@ -2073,11 +2083,11 @@ static int unix_seqpacket_recvmsg(struct socket *sock, struct msghdr *msg,
 
 static void unix_copy_addr(struct msghdr *msg, struct sock *sk)
 {
-       struct unix_sock *u = unix_sk(sk);
+       struct unix_address *addr = smp_load_acquire(&unix_sk(sk)->addr);
 
-       if (u->addr) {
-               msg->msg_namelen = u->addr->len;
-               memcpy(msg->msg_name, u->addr->name, u->addr->len);
+       if (addr) {
+               msg->msg_namelen = addr->len;
+               memcpy(msg->msg_name, addr->name, addr->len);
        }
 }
 
@@ -2581,15 +2591,14 @@ static int unix_open_file(struct sock *sk)
        if (!ns_capable(sock_net(sk)->user_ns, CAP_NET_ADMIN))
                return -EPERM;
 
-       unix_state_lock(sk);
+       if (!smp_load_acquire(&unix_sk(sk)->addr))
+               return -ENOENT;
+
        path = unix_sk(sk)->path;
-       if (!path.dentry) {
-               unix_state_unlock(sk);
+       if (!path.dentry)
                return -ENOENT;
-       }
 
        path_get(&path);
-       unix_state_unlock(sk);
 
        fd = get_unused_fd_flags(O_CLOEXEC);
        if (fd < 0)
@@ -2830,7 +2839,7 @@ static int unix_seq_show(struct seq_file *seq, void *v)
                        (s->sk_state == TCP_ESTABLISHED ? SS_CONNECTING : SS_DISCONNECTING),
                        sock_i_ino(s));
 
-               if (u->addr) {
+               if (u->addr) {  // under unix_table_lock here
                        int i, len;
                        seq_putc(seq, ' ');
 
index 384c84e..3183d9b 100644 (file)
@@ -10,7 +10,8 @@
 
 static int sk_diag_dump_name(struct sock *sk, struct sk_buff *nlskb)
 {
-       struct unix_address *addr = unix_sk(sk)->addr;
+       /* might or might not have unix_table_lock */
+       struct unix_address *addr = smp_load_acquire(&unix_sk(sk)->addr);
 
        if (!addr)
                return 0;
index 5d3cce9..15eb5d3 100644 (file)
@@ -75,6 +75,9 @@ static u32 virtio_transport_get_local_cid(void)
 {
        struct virtio_vsock *vsock = virtio_vsock_get();
 
+       if (!vsock)
+               return VMADDR_CID_ANY;
+
        return vsock->guest_cid;
 }
 
@@ -584,10 +587,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
 
        virtio_vsock_update_guest_cid(vsock);
 
-       ret = vsock_core_init(&virtio_transport.transport);
-       if (ret < 0)
-               goto out_vqs;
-
        vsock->rx_buf_nr = 0;
        vsock->rx_buf_max_nr = 0;
        atomic_set(&vsock->queued_replies, 0);
@@ -618,8 +617,6 @@ static int virtio_vsock_probe(struct virtio_device *vdev)
        mutex_unlock(&the_virtio_vsock_mutex);
        return 0;
 
-out_vqs:
-       vsock->vdev->config->del_vqs(vsock->vdev);
 out:
        kfree(vsock);
        mutex_unlock(&the_virtio_vsock_mutex);
@@ -637,6 +634,9 @@ static void virtio_vsock_remove(struct virtio_device *vdev)
        flush_work(&vsock->event_work);
        flush_work(&vsock->send_pkt_work);
 
+       /* Reset all connected sockets when the device disappear */
+       vsock_for_each_connected_socket(virtio_vsock_reset_sock);
+
        vdev->config->reset(vdev);
 
        mutex_lock(&vsock->rx_lock);
@@ -669,7 +669,6 @@ static void virtio_vsock_remove(struct virtio_device *vdev)
 
        mutex_lock(&the_virtio_vsock_mutex);
        the_virtio_vsock = NULL;
-       vsock_core_exit();
        mutex_unlock(&the_virtio_vsock_mutex);
 
        vdev->config->del_vqs(vdev);
@@ -702,14 +701,28 @@ static int __init virtio_vsock_init(void)
        virtio_vsock_workqueue = alloc_workqueue("virtio_vsock", 0, 0);
        if (!virtio_vsock_workqueue)
                return -ENOMEM;
+
        ret = register_virtio_driver(&virtio_vsock_driver);
        if (ret)
-               destroy_workqueue(virtio_vsock_workqueue);
+               goto out_wq;
+
+       ret = vsock_core_init(&virtio_transport.transport);
+       if (ret)
+               goto out_vdr;
+
+       return 0;
+
+out_vdr:
+       unregister_virtio_driver(&virtio_vsock_driver);
+out_wq:
+       destroy_workqueue(virtio_vsock_workqueue);
        return ret;
+
 }
 
 static void __exit virtio_vsock_exit(void)
 {
+       vsock_core_exit();
        unregister_virtio_driver(&virtio_vsock_driver);
        destroy_workqueue(virtio_vsock_workqueue);
 }
index c361ce7..c3d5ab0 100644 (file)
@@ -1651,6 +1651,10 @@ static void vmci_transport_cleanup(struct work_struct *work)
 
 static void vmci_transport_destruct(struct vsock_sock *vsk)
 {
+       /* transport can be NULL if we hit a failure at init() time */
+       if (!vmci_trans(vsk))
+               return;
+
        /* Ensure that the detach callback doesn't use the sk/vsk
         * we are about to destruct.
         */
index 882d97b..550ac9d 100644 (file)
@@ -41,6 +41,8 @@ int __cfg80211_stop_ap(struct cfg80211_registered_device *rdev,
                cfg80211_sched_dfs_chan_update(rdev);
        }
 
+       schedule_work(&cfg80211_disconnect_work);
+
        return err;
 }
 
index 623dfe5..b36ad8e 100644 (file)
@@ -1068,6 +1068,8 @@ static void __cfg80211_unregister_wdev(struct wireless_dev *wdev, bool sync)
 
        ASSERT_RTNL();
 
+       flush_work(&wdev->pmsr_free_wk);
+
        nl80211_notify_iface(rdev, wdev, NL80211_CMD_DEL_INTERFACE);
 
        list_del_rcu(&wdev->list);
index c5d6f34..f6b4056 100644 (file)
@@ -445,6 +445,8 @@ void cfg80211_process_wdev_events(struct wireless_dev *wdev);
 bool cfg80211_does_bw_fit_range(const struct ieee80211_freq_range *freq_range,
                                u32 center_freq_khz, u32 bw_khz);
 
+extern struct work_struct cfg80211_disconnect_work;
+
 /**
  * cfg80211_chandef_dfs_usable - checks if chandef is DFS usable
  * @wiphy: the wiphy to validate against
index 5e49492..d91a408 100644 (file)
@@ -250,7 +250,7 @@ nl80211_pmsr_ftm_req_attr_policy[NL80211_PMSR_FTM_REQ_ATTR_MAX + 1] = {
        [NL80211_PMSR_FTM_REQ_ATTR_BURST_DURATION] =
                NLA_POLICY_MAX(NLA_U8, 15),
        [NL80211_PMSR_FTM_REQ_ATTR_FTMS_PER_BURST] =
-               NLA_POLICY_MAX(NLA_U8, 15),
+               NLA_POLICY_MAX(NLA_U8, 31),
        [NL80211_PMSR_FTM_REQ_ATTR_NUM_FTMR_RETRIES] = { .type = NLA_U8 },
        [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_LCI] = { .type = NLA_FLAG },
        [NL80211_PMSR_FTM_REQ_ATTR_REQUEST_CIVICLOC] = { .type = NLA_FLAG },
@@ -555,7 +555,7 @@ const struct nla_policy nl80211_policy[NUM_NL80211_ATTR] = {
        },
        [NL80211_ATTR_TIMEOUT] = NLA_POLICY_MIN(NLA_U32, 1),
        [NL80211_ATTR_PEER_MEASUREMENTS] =
-               NLA_POLICY_NESTED(NL80211_PMSR_FTM_REQ_ATTR_MAX,
+               NLA_POLICY_NESTED(NL80211_PMSR_ATTR_MAX,
                                  nl80211_pmsr_attr_policy),
 };
 
index de92867..0216ab5 100644 (file)
@@ -256,8 +256,7 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info)
                if (err)
                        goto out_err;
        } else {
-               memcpy(req->mac_addr, nla_data(info->attrs[NL80211_ATTR_MAC]),
-                      ETH_ALEN);
+               memcpy(req->mac_addr, wdev_address(wdev), ETH_ALEN);
                memset(req->mac_addr_mask, 0xff, ETH_ALEN);
        }
 
@@ -272,6 +271,7 @@ int nl80211_pmsr_start(struct sk_buff *skb, struct genl_info *info)
 
        req->n_peers = count;
        req->cookie = cfg80211_assign_cookie(rdev);
+       req->nl_portid = info->snd_portid;
 
        err = rdev_start_pmsr(rdev, wdev, req);
        if (err)
@@ -530,14 +530,14 @@ free:
 }
 EXPORT_SYMBOL_GPL(cfg80211_pmsr_report);
 
-void cfg80211_pmsr_free_wk(struct work_struct *work)
+static void cfg80211_pmsr_process_abort(struct wireless_dev *wdev)
 {
-       struct wireless_dev *wdev = container_of(work, struct wireless_dev,
-                                                pmsr_free_wk);
        struct cfg80211_registered_device *rdev = wiphy_to_rdev(wdev->wiphy);
        struct cfg80211_pmsr_request *req, *tmp;
        LIST_HEAD(free_list);
 
+       lockdep_assert_held(&wdev->mtx);
+
        spin_lock_bh(&wdev->pmsr_lock);
        list_for_each_entry_safe(req, tmp, &wdev->pmsr_list, list) {
                if (req->nl_portid)
@@ -547,14 +547,22 @@ void cfg80211_pmsr_free_wk(struct work_struct *work)
        spin_unlock_bh(&wdev->pmsr_lock);
 
        list_for_each_entry_safe(req, tmp, &free_list, list) {
-               wdev_lock(wdev);
                rdev_abort_pmsr(rdev, wdev, req);
-               wdev_unlock(wdev);
 
                kfree(req);
        }
 }
 
+void cfg80211_pmsr_free_wk(struct work_struct *work)
+{
+       struct wireless_dev *wdev = container_of(work, struct wireless_dev,
+                                                pmsr_free_wk);
+
+       wdev_lock(wdev);
+       cfg80211_pmsr_process_abort(wdev);
+       wdev_unlock(wdev);
+}
+
 void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev)
 {
        struct cfg80211_pmsr_request *req;
@@ -568,8 +576,8 @@ void cfg80211_pmsr_wdev_down(struct wireless_dev *wdev)
        spin_unlock_bh(&wdev->pmsr_lock);
 
        if (found)
-               schedule_work(&wdev->pmsr_free_wk);
-       flush_work(&wdev->pmsr_free_wk);
+               cfg80211_pmsr_process_abort(wdev);
+
        WARN_ON(!list_empty(&wdev->pmsr_list));
 }
 
index ecfb1a0..dd58b99 100644 (file)
@@ -1024,8 +1024,13 @@ static void regdb_fw_cb(const struct firmware *fw, void *context)
        }
 
        rtnl_lock();
-       if (WARN_ON(regdb && !IS_ERR(regdb))) {
-               /* just restore and free new db */
+       if (regdb && !IS_ERR(regdb)) {
+               /* negative case - a bug
+                * positive case - can happen due to race in case of multiple cb's in
+                * queue, due to usage of asynchronous callback
+                *
+                * Either case, just restore and free new db.
+                */
        } else if (set_error) {
                regdb = ERR_PTR(set_error);
        } else if (fw) {
@@ -1255,7 +1260,7 @@ static bool is_valid_rd(const struct ieee80211_regdomain *rd)
  * definitions (the "2.4 GHz band", the "5 GHz band" and the "60GHz band"),
  * however it is safe for now to assume that a frequency rule should not be
  * part of a frequency's band if the start freq or end freq are off by more
- * than 2 GHz for the 2.4 and 5 GHz bands, and by more than 10 GHz for the
+ * than 2 GHz for the 2.4 and 5 GHz bands, and by more than 20 GHz for the
  * 60 GHz band.
  * This resolution can be lowered and should be considered as we add
  * regulatory rule support for other "bands".
@@ -1270,7 +1275,7 @@ static bool freq_in_rule_band(const struct ieee80211_freq_range *freq_range,
         * with the Channel starting frequency above 45 GHz.
         */
        u32 limit = freq_khz > 45 * ONE_GHZ_IN_KHZ ?
-                       10 * ONE_GHZ_IN_KHZ : 2 * ONE_GHZ_IN_KHZ;
+                       20 * ONE_GHZ_IN_KHZ : 2 * ONE_GHZ_IN_KHZ;
        if (abs(freq_khz - freq_range->start_freq_khz) <= limit)
                return true;
        if (abs(freq_khz - freq_range->end_freq_khz) <= limit)
index f741d83..7d34cb8 100644 (file)
@@ -667,7 +667,7 @@ static void disconnect_work(struct work_struct *work)
        rtnl_unlock();
 }
 
-static DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
+DECLARE_WORK(cfg80211_disconnect_work, disconnect_work);
 
 
 /*
index cd48cdd..ec30e37 100644 (file)
@@ -5,7 +5,7 @@
  * Copyright 2007-2009 Johannes Berg <johannes@sipsolutions.net>
  * Copyright 2013-2014  Intel Mobile Communications GmbH
  * Copyright 2017      Intel Deutschland GmbH
- * Copyright (C) 2018 Intel Corporation
+ * Copyright (C) 2018-2019 Intel Corporation
  */
 #include <linux/export.h>
 #include <linux/bitops.h>
@@ -19,6 +19,7 @@
 #include <linux/mpls.h>
 #include <linux/gcd.h>
 #include <linux/bitfield.h>
+#include <linux/nospec.h>
 #include "core.h"
 #include "rdev-ops.h"
 
@@ -715,20 +716,25 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
 {
        unsigned int dscp;
        unsigned char vlan_priority;
+       unsigned int ret;
 
        /* skb->priority values from 256->263 are magic values to
         * directly indicate a specific 802.1d priority.  This is used
         * to allow 802.1d priority to be passed directly in from VLAN
         * tags, etc.
         */
-       if (skb->priority >= 256 && skb->priority <= 263)
-               return skb->priority - 256;
+       if (skb->priority >= 256 && skb->priority <= 263) {
+               ret = skb->priority - 256;
+               goto out;
+       }
 
        if (skb_vlan_tag_present(skb)) {
                vlan_priority = (skb_vlan_tag_get(skb) & VLAN_PRIO_MASK)
                        >> VLAN_PRIO_SHIFT;
-               if (vlan_priority > 0)
-                       return vlan_priority;
+               if (vlan_priority > 0) {
+                       ret = vlan_priority;
+                       goto out;
+               }
        }
 
        switch (skb->protocol) {
@@ -747,8 +753,9 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
                if (!mpls)
                        return 0;
 
-               return (ntohl(mpls->entry) & MPLS_LS_TC_MASK)
+               ret = (ntohl(mpls->entry) & MPLS_LS_TC_MASK)
                        >> MPLS_LS_TC_SHIFT;
+               goto out;
        }
        case htons(ETH_P_80221):
                /* 802.21 is always network control traffic */
@@ -761,18 +768,24 @@ unsigned int cfg80211_classify8021d(struct sk_buff *skb,
                unsigned int i, tmp_dscp = dscp >> 2;
 
                for (i = 0; i < qos_map->num_des; i++) {
-                       if (tmp_dscp == qos_map->dscp_exception[i].dscp)
-                               return qos_map->dscp_exception[i].up;
+                       if (tmp_dscp == qos_map->dscp_exception[i].dscp) {
+                               ret = qos_map->dscp_exception[i].up;
+                               goto out;
+                       }
                }
 
                for (i = 0; i < 8; i++) {
                        if (tmp_dscp >= qos_map->up[i].low &&
-                           tmp_dscp <= qos_map->up[i].high)
-                               return i;
+                           tmp_dscp <= qos_map->up[i].high) {
+                               ret = i;
+                               goto out;
+                       }
                }
        }
 
-       return dscp >> 5;
+       ret = dscp >> 5;
+out:
+       return array_index_nospec(ret, IEEE80211_NUM_TIDS);
 }
 EXPORT_SYMBOL(cfg80211_classify8021d);
 
index 5121729..eff3134 100644 (file)
@@ -352,17 +352,15 @@ static unsigned int x25_new_lci(struct x25_neigh *nb)
        unsigned int lci = 1;
        struct sock *sk;
 
-       read_lock_bh(&x25_list_lock);
-
-       while ((sk = __x25_find_socket(lci, nb)) != NULL) {
+       while ((sk = x25_find_socket(lci, nb)) != NULL) {
                sock_put(sk);
                if (++lci == 4096) {
                        lci = 0;
                        break;
                }
+               cond_resched();
        }
 
-       read_unlock_bh(&x25_list_lock);
        return lci;
 }
 
@@ -681,8 +679,7 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        struct sockaddr_x25 *addr = (struct sockaddr_x25 *)uaddr;
        int len, i, rc = 0;
 
-       if (!sock_flag(sk, SOCK_ZAPPED) ||
-           addr_len != sizeof(struct sockaddr_x25) ||
+       if (addr_len != sizeof(struct sockaddr_x25) ||
            addr->sx25_family != AF_X25) {
                rc = -EINVAL;
                goto out;
@@ -701,9 +698,13 @@ static int x25_bind(struct socket *sock, struct sockaddr *uaddr, int addr_len)
        }
 
        lock_sock(sk);
-       x25_sk(sk)->source_addr = addr->sx25_addr;
-       x25_insert_socket(sk);
-       sock_reset_flag(sk, SOCK_ZAPPED);
+       if (sock_flag(sk, SOCK_ZAPPED)) {
+               x25_sk(sk)->source_addr = addr->sx25_addr;
+               x25_insert_socket(sk);
+               sock_reset_flag(sk, SOCK_ZAPPED);
+       } else {
+               rc = -EINVAL;
+       }
        release_sock(sk);
        SOCK_DEBUG(sk, "x25_bind: socket is bound\n");
 out:
index a264cf2..37e1fe1 100644 (file)
@@ -41,13 +41,20 @@ void xdp_del_sk_umem(struct xdp_umem *umem, struct xdp_sock *xs)
  * not know if the device has more tx queues than rx, or the opposite.
  * This might also change during run time.
  */
-static void xdp_reg_umem_at_qid(struct net_device *dev, struct xdp_umem *umem,
-                               u16 queue_id)
+static int xdp_reg_umem_at_qid(struct net_device *dev, struct xdp_umem *umem,
+                              u16 queue_id)
 {
+       if (queue_id >= max_t(unsigned int,
+                             dev->real_num_rx_queues,
+                             dev->real_num_tx_queues))
+               return -EINVAL;
+
        if (queue_id < dev->real_num_rx_queues)
                dev->_rx[queue_id].umem = umem;
        if (queue_id < dev->real_num_tx_queues)
                dev->_tx[queue_id].umem = umem;
+
+       return 0;
 }
 
 struct xdp_umem *xdp_get_umem_from_qid(struct net_device *dev,
@@ -88,7 +95,10 @@ int xdp_umem_assign_dev(struct xdp_umem *umem, struct net_device *dev,
                goto out_rtnl_unlock;
        }
 
-       xdp_reg_umem_at_qid(dev, umem, queue_id);
+       err = xdp_reg_umem_at_qid(dev, umem, queue_id);
+       if (err)
+               goto out_rtnl_unlock;
+
        umem->dev = dev;
        umem->queue_id = queue_id;
        if (force_copy)
@@ -115,9 +125,10 @@ int xdp_umem_assign_dev(struct xdp_umem *umem, struct net_device *dev,
        return 0;
 
 err_unreg_umem:
-       xdp_clear_umem_at_qid(dev, queue_id);
        if (!force_zc)
                err = 0; /* fallback to copy mode */
+       if (err)
+               xdp_clear_umem_at_qid(dev, queue_id);
 out_rtnl_unlock:
        rtnl_unlock();
        return err;
@@ -249,10 +260,10 @@ static int xdp_umem_pin_pages(struct xdp_umem *umem)
        if (!umem->pgs)
                return -ENOMEM;
 
-       down_write(&current->mm->mmap_sem);
-       npgs = get_user_pages(umem->address, umem->npgs,
-                             gup_flags, &umem->pgs[0], NULL);
-       up_write(&current->mm->mmap_sem);
+       down_read(&current->mm->mmap_sem);
+       npgs = get_user_pages_longterm(umem->address, umem->npgs,
+                                      gup_flags, &umem->pgs[0], NULL);
+       up_read(&current->mm->mmap_sem);
 
        if (npgs != umem->npgs) {
                if (npgs >= 0) {
index a032684..85e4fe4 100644 (file)
@@ -366,7 +366,6 @@ static int xsk_release(struct socket *sock)
 
        xskq_destroy(xs->rx);
        xskq_destroy(xs->tx);
-       xdp_put_umem(xs->umem);
 
        sock_orphan(sk);
        sock->sk = NULL;
@@ -669,6 +668,8 @@ static int xsk_mmap(struct file *file, struct socket *sock,
                if (!umem)
                        return -EINVAL;
 
+               /* Matches the smp_wmb() in XDP_UMEM_REG */
+               smp_rmb();
                if (offset == XDP_UMEM_PGOFF_FILL_RING)
                        q = READ_ONCE(umem->fq);
                else if (offset == XDP_UMEM_PGOFF_COMPLETION_RING)
@@ -678,6 +679,8 @@ static int xsk_mmap(struct file *file, struct socket *sock,
        if (!q)
                return -EINVAL;
 
+       /* Matches the smp_wmb() in xsk_init_queue */
+       smp_rmb();
        qpg = virt_to_head_page(q->ring);
        if (size > (PAGE_SIZE << compound_order(qpg)))
                return -EINVAL;
@@ -714,6 +717,18 @@ static const struct proto_ops xsk_proto_ops = {
        .sendpage       = sock_no_sendpage,
 };
 
+static void xsk_destruct(struct sock *sk)
+{
+       struct xdp_sock *xs = xdp_sk(sk);
+
+       if (!sock_flag(sk, SOCK_DEAD))
+               return;
+
+       xdp_put_umem(xs->umem);
+
+       sk_refcnt_debug_dec(sk);
+}
+
 static int xsk_create(struct net *net, struct socket *sock, int protocol,
                      int kern)
 {
@@ -740,6 +755,9 @@ static int xsk_create(struct net *net, struct socket *sock, int protocol,
 
        sk->sk_family = PF_XDP;
 
+       sk->sk_destruct = xsk_destruct;
+       sk_refcnt_debug_inc(sk);
+
        sock_set_flag(sk, SOCK_RCU_FREE);
 
        xs = xdp_sk(sk);
index 6be8c7d..dbb3c19 100644 (file)
@@ -76,10 +76,10 @@ static struct xfrm_if *xfrmi_decode_session(struct sk_buff *skb)
        int ifindex;
        struct xfrm_if *xi;
 
-       if (!skb->dev)
+       if (!secpath_exists(skb) || !skb->dev)
                return NULL;
 
-       xfrmn = net_generic(dev_net(skb->dev), xfrmi_net_id);
+       xfrmn = net_generic(xs_net(xfrm_input_state(skb)), xfrmi_net_id);
        ifindex = skb->dev->ifindex;
 
        for_each_xfrmi_rcu(xfrmn->xfrmi[0], xi) {
index 934492b..8d1a898 100644 (file)
@@ -680,16 +680,6 @@ static void xfrm_hash_resize(struct work_struct *work)
        mutex_unlock(&hash_resize_mutex);
 }
 
-static void xfrm_hash_reset_inexact_table(struct net *net)
-{
-       struct xfrm_pol_inexact_bin *b;
-
-       lockdep_assert_held(&net->xfrm.xfrm_policy_lock);
-
-       list_for_each_entry(b, &net->xfrm.inexact_bins, inexact_bins)
-               INIT_HLIST_HEAD(&b->hhead);
-}
-
 /* Make sure *pol can be inserted into fastbin.
  * Useful to check that later insert requests will be sucessful
  * (provided xfrm_policy_lock is held throughout).
@@ -833,13 +823,13 @@ static void xfrm_policy_inexact_list_reinsert(struct net *net,
                                              u16 family)
 {
        unsigned int matched_s, matched_d;
-       struct hlist_node *newpos = NULL;
        struct xfrm_policy *policy, *p;
 
        matched_s = 0;
        matched_d = 0;
 
        list_for_each_entry_reverse(policy, &net->xfrm.policy_all, walk.all) {
+               struct hlist_node *newpos = NULL;
                bool matches_s, matches_d;
 
                if (!policy->bydst_reinsert)
@@ -849,16 +839,19 @@ static void xfrm_policy_inexact_list_reinsert(struct net *net,
 
                policy->bydst_reinsert = false;
                hlist_for_each_entry(p, &n->hhead, bydst) {
-                       if (policy->priority >= p->priority)
+                       if (policy->priority > p->priority)
+                               newpos = &p->bydst;
+                       else if (policy->priority == p->priority &&
+                                policy->pos > p->pos)
                                newpos = &p->bydst;
                        else
                                break;
                }
 
                if (newpos)
-                       hlist_add_behind(&policy->bydst, newpos);
+                       hlist_add_behind_rcu(&policy->bydst, newpos);
                else
-                       hlist_add_head(&policy->bydst, &n->hhead);
+                       hlist_add_head_rcu(&policy->bydst, &n->hhead);
 
                /* paranoia checks follow.
                 * Check that the reinserted policy matches at least
@@ -893,12 +886,13 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net,
                                              struct rb_root *new,
                                              u16 family)
 {
-       struct rb_node **p, *parent = NULL;
        struct xfrm_pol_inexact_node *node;
+       struct rb_node **p, *parent;
 
        /* we should not have another subtree here */
        WARN_ON_ONCE(!RB_EMPTY_ROOT(&n->root));
-
+restart:
+       parent = NULL;
        p = &new->rb_node;
        while (*p) {
                u8 prefixlen;
@@ -918,12 +912,11 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net,
                } else {
                        struct xfrm_policy *tmp;
 
-                       hlist_for_each_entry(tmp, &node->hhead, bydst)
-                               tmp->bydst_reinsert = true;
-                       hlist_for_each_entry(tmp, &n->hhead, bydst)
+                       hlist_for_each_entry(tmp, &n->hhead, bydst) {
                                tmp->bydst_reinsert = true;
+                               hlist_del_rcu(&tmp->bydst);
+                       }
 
-                       INIT_HLIST_HEAD(&node->hhead);
                        xfrm_policy_inexact_list_reinsert(net, node, family);
 
                        if (node->prefixlen == n->prefixlen) {
@@ -935,8 +928,7 @@ static void xfrm_policy_inexact_node_reinsert(struct net *net,
                        kfree_rcu(n, rcu);
                        n = node;
                        n->prefixlen = prefixlen;
-                       *p = new->rb_node;
-                       parent = NULL;
+                       goto restart;
                }
        }
 
@@ -965,12 +957,11 @@ static void xfrm_policy_inexact_node_merge(struct net *net,
                                                  family);
        }
 
-       hlist_for_each_entry(tmp, &v->hhead, bydst)
-               tmp->bydst_reinsert = true;
-       hlist_for_each_entry(tmp, &n->hhead, bydst)
+       hlist_for_each_entry(tmp, &v->hhead, bydst) {
                tmp->bydst_reinsert = true;
+               hlist_del_rcu(&tmp->bydst);
+       }
 
-       INIT_HLIST_HEAD(&n->hhead);
        xfrm_policy_inexact_list_reinsert(net, n, family);
 }
 
@@ -1235,6 +1226,7 @@ static void xfrm_hash_rebuild(struct work_struct *work)
        } while (read_seqretry(&net->xfrm.policy_hthresh.lock, seq));
 
        spin_lock_bh(&net->xfrm.xfrm_policy_lock);
+       write_seqcount_begin(&xfrm_policy_hash_generation);
 
        /* make sure that we can insert the indirect policies again before
         * we start with destructive action.
@@ -1278,10 +1270,14 @@ static void xfrm_hash_rebuild(struct work_struct *work)
        }
 
        /* reset the bydst and inexact table in all directions */
-       xfrm_hash_reset_inexact_table(net);
-
        for (dir = 0; dir < XFRM_POLICY_MAX; dir++) {
-               INIT_HLIST_HEAD(&net->xfrm.policy_inexact[dir]);
+               struct hlist_node *n;
+
+               hlist_for_each_entry_safe(policy, n,
+                                         &net->xfrm.policy_inexact[dir],
+                                         bydst_inexact_list)
+                       hlist_del_init(&policy->bydst_inexact_list);
+
                hmask = net->xfrm.policy_bydst[dir].hmask;
                odst = net->xfrm.policy_bydst[dir].table;
                for (i = hmask; i >= 0; i--)
@@ -1313,6 +1309,9 @@ static void xfrm_hash_rebuild(struct work_struct *work)
                newpos = NULL;
                chain = policy_hash_bysel(net, &policy->selector,
                                          policy->family, dir);
+
+               hlist_del_rcu(&policy->bydst);
+
                if (!chain) {
                        void *p = xfrm_policy_inexact_insert(policy, dir, 0);
 
@@ -1334,6 +1333,7 @@ static void xfrm_hash_rebuild(struct work_struct *work)
 
 out_unlock:
        __xfrm_policy_inexact_flush(net);
+       write_seqcount_end(&xfrm_policy_hash_generation);
        spin_unlock_bh(&net->xfrm.xfrm_policy_lock);
 
        mutex_unlock(&hash_resize_mutex);
@@ -2600,7 +2600,10 @@ static struct dst_entry *xfrm_bundle_create(struct xfrm_policy *policy,
                dst_copy_metrics(dst1, dst);
 
                if (xfrm[i]->props.mode != XFRM_MODE_TRANSPORT) {
-                       __u32 mark = xfrm_smark_get(fl->flowi_mark, xfrm[i]);
+                       __u32 mark = 0;
+
+                       if (xfrm[i]->props.smark.v || xfrm[i]->props.smark.m)
+                               mark = xfrm_smark_get(fl->flowi_mark, xfrm[i]);
 
                        family = xfrm[i]->props.family;
                        dst = xfrm_dst_lookup(xfrm[i], tos, fl->flowi_oif,
@@ -3311,8 +3314,10 @@ int __xfrm_policy_check(struct sock *sk, int dir, struct sk_buff *skb,
 
        if (ifcb) {
                xi = ifcb->decode_session(skb);
-               if (xi)
+               if (xi) {
                        if_id = xi->p.if_id;
+                       net = xi->net;
+               }
        }
        rcu_read_unlock();
 
index 23c9289..1bb971f 100644 (file)
@@ -432,7 +432,7 @@ void xfrm_state_free(struct xfrm_state *x)
 }
 EXPORT_SYMBOL(xfrm_state_free);
 
-static void xfrm_state_gc_destroy(struct xfrm_state *x)
+static void ___xfrm_state_destroy(struct xfrm_state *x)
 {
        tasklet_hrtimer_cancel(&x->mtimer);
        del_timer_sync(&x->rtimer);
@@ -474,7 +474,7 @@ static void xfrm_state_gc_task(struct work_struct *work)
        synchronize_rcu();
 
        hlist_for_each_entry_safe(x, tmp, &gc_list, gclist)
-               xfrm_state_gc_destroy(x);
+               ___xfrm_state_destroy(x);
 }
 
 static enum hrtimer_restart xfrm_timer_handler(struct hrtimer *me)
@@ -598,14 +598,19 @@ struct xfrm_state *xfrm_state_alloc(struct net *net)
 }
 EXPORT_SYMBOL(xfrm_state_alloc);
 
-void __xfrm_state_destroy(struct xfrm_state *x)
+void __xfrm_state_destroy(struct xfrm_state *x, bool sync)
 {
        WARN_ON(x->km.state != XFRM_STATE_DEAD);
 
-       spin_lock_bh(&xfrm_state_gc_lock);
-       hlist_add_head(&x->gclist, &xfrm_state_gc_list);
-       spin_unlock_bh(&xfrm_state_gc_lock);
-       schedule_work(&xfrm_state_gc_work);
+       if (sync) {
+               synchronize_rcu();
+               ___xfrm_state_destroy(x);
+       } else {
+               spin_lock_bh(&xfrm_state_gc_lock);
+               hlist_add_head(&x->gclist, &xfrm_state_gc_list);
+               spin_unlock_bh(&xfrm_state_gc_lock);
+               schedule_work(&xfrm_state_gc_work);
+       }
 }
 EXPORT_SYMBOL(__xfrm_state_destroy);
 
@@ -708,7 +713,7 @@ xfrm_dev_state_flush_secctx_check(struct net *net, struct net_device *dev, bool
 }
 #endif
 
-int xfrm_state_flush(struct net *net, u8 proto, bool task_valid)
+int xfrm_state_flush(struct net *net, u8 proto, bool task_valid, bool sync)
 {
        int i, err = 0, cnt = 0;
 
@@ -730,7 +735,10 @@ restart:
                                err = xfrm_state_delete(x);
                                xfrm_audit_state_delete(x, err ? 0 : 1,
                                                        task_valid);
-                               xfrm_state_put(x);
+                               if (sync)
+                                       xfrm_state_put_sync(x);
+                               else
+                                       xfrm_state_put(x);
                                if (!err)
                                        cnt++;
 
@@ -2215,7 +2223,7 @@ void xfrm_state_delete_tunnel(struct xfrm_state *x)
                if (atomic_read(&t->tunnel_users) == 2)
                        xfrm_state_delete(t);
                atomic_dec(&t->tunnel_users);
-               xfrm_state_put(t);
+               xfrm_state_put_sync(t);
                x->tunnel = NULL;
        }
 }
@@ -2375,8 +2383,8 @@ void xfrm_state_fini(struct net *net)
        unsigned int sz;
 
        flush_work(&net->xfrm.state_hash_work);
-       xfrm_state_flush(net, IPSEC_PROTO_ANY, false);
        flush_work(&xfrm_state_gc_work);
+       xfrm_state_flush(net, IPSEC_PROTO_ANY, false, true);
 
        WARN_ON(!list_empty(&net->xfrm.state_all));
 
index 277c1c4..a131f9f 100644 (file)
@@ -1488,10 +1488,15 @@ static int validate_tmpl(int nr, struct xfrm_user_tmpl *ut, u16 family)
                if (!ut[i].family)
                        ut[i].family = family;
 
-               if ((ut[i].mode == XFRM_MODE_TRANSPORT) &&
-                   (ut[i].family != prev_family))
-                       return -EINVAL;
-
+               switch (ut[i].mode) {
+               case XFRM_MODE_TUNNEL:
+               case XFRM_MODE_BEET:
+                       break;
+               default:
+                       if (ut[i].family != prev_family)
+                               return -EINVAL;
+                       break;
+               }
                if (ut[i].mode >= XFRM_MODE_MAX)
                        return -EINVAL;
 
@@ -1927,7 +1932,7 @@ static int xfrm_flush_sa(struct sk_buff *skb, struct nlmsghdr *nlh,
        struct xfrm_usersa_flush *p = nlmsg_data(nlh);
        int err;
 
-       err = xfrm_state_flush(net, p->proto, true);
+       err = xfrm_state_flush(net, p->proto, true, false);
        if (err) {
                if (err == -ESRCH) /* empty table */
                        return 0;
index 66ae15f..db1a91d 100644 (file)
@@ -279,6 +279,7 @@ $(obj)/%.o: $(src)/%.c
                -Wno-gnu-variable-sized-type-not-at-end \
                -Wno-address-of-packed-member -Wno-tautological-compare \
                -Wno-unknown-warning-option $(CLANG_ARCH_ARGS) \
+               -I$(srctree)/samples/bpf/ -include asm_goto_workaround.h \
                -O2 -emit-llvm -c $< -o -| $(LLC) -march=bpf $(LLC_FLAGS) -filetype=obj -o $@
 ifeq ($(DWARF2BTF),y)
        $(BTF_PAHOLE) -J $@
diff --git a/samples/bpf/asm_goto_workaround.h b/samples/bpf/asm_goto_workaround.h
new file mode 100644 (file)
index 0000000..5cd7c1d
--- /dev/null
@@ -0,0 +1,16 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright (c) 2019 Facebook */
+#ifndef __ASM_GOTO_WORKAROUND_H
+#define __ASM_GOTO_WORKAROUND_H
+
+/* this will bring in asm_volatile_goto macro definition
+ * if enabled by compiler and config options.
+ */
+#include <linux/types.h>
+
+#ifdef asm_volatile_goto
+#undef asm_volatile_goto
+#define asm_volatile_goto(x...) asm volatile("invalid use of asm_volatile_goto")
+#endif
+
+#endif
index d7b68ef..0bb6507 100644 (file)
@@ -77,7 +77,7 @@ static int test_foo_bar(void)
 
        /* Create cgroup /foo, get fd, and join it */
        foo = create_and_get_cgroup(FOO);
-       if (!foo)
+       if (foo < 0)
                goto err;
 
        if (join_cgroup(FOO))
@@ -94,7 +94,7 @@ static int test_foo_bar(void)
 
        /* Create cgroup /foo/bar, get fd, and join it */
        bar = create_and_get_cgroup(BAR);
-       if (!bar)
+       if (bar < 0)
                goto err;
 
        if (join_cgroup(BAR))
@@ -298,19 +298,19 @@ static int test_multiprog(void)
                goto err;
 
        cg1 = create_and_get_cgroup("/cg1");
-       if (!cg1)
+       if (cg1 < 0)
                goto err;
        cg2 = create_and_get_cgroup("/cg1/cg2");
-       if (!cg2)
+       if (cg2 < 0)
                goto err;
        cg3 = create_and_get_cgroup("/cg1/cg2/cg3");
-       if (!cg3)
+       if (cg3 < 0)
                goto err;
        cg4 = create_and_get_cgroup("/cg1/cg2/cg3/cg4");
-       if (!cg4)
+       if (cg4 < 0)
                goto err;
        cg5 = create_and_get_cgroup("/cg1/cg2/cg3/cg4/cg5");
-       if (!cg5)
+       if (cg5 < 0)
                goto err;
 
        if (join_cgroup("/cg1/cg2/cg3/cg4/cg5"))
index 2259f99..f082d6a 100644 (file)
@@ -32,7 +32,7 @@ int main(int argc, char **argv)
 
        cg2 = create_and_get_cgroup(CGROUP_PATH);
 
-       if (!cg2)
+       if (cg2 < 0)
                goto err;
 
        if (bpf_map_update_elem(map_fd[0], &idx, &cg2, BPF_ANY)) {
index 0a197f8..8bfda95 100644 (file)
@@ -103,7 +103,7 @@ int main(int argc, char **argv)
                return 1;
        }
 
-       ifindex = if_nametoindex(argv[1]);
+       ifindex = if_nametoindex(argv[optind]);
        if (!ifindex) {
                perror("if_nametoindex");
                return 1;
index 33e67bd..3223448 100644 (file)
@@ -117,7 +117,7 @@ static bool mei_init(struct mei *me, const uuid_le *guid,
 
        me->verbose = verbose;
 
-       me->fd = open("/dev/mei", O_RDWR);
+       me->fd = open("/dev/mei0", O_RDWR);
        if (me->fd == -1) {
                mei_err(me, "Cannot establish a handle to the Intel MEI driver\n");
                goto err;
index 4920903..fb43a81 100644 (file)
@@ -34,6 +34,7 @@ HOSTCFLAGS_bpf-direct.o += $(MFLAG)
 HOSTCFLAGS_dropper.o += $(MFLAG)
 HOSTCFLAGS_bpf-helper.o += $(MFLAG)
 HOSTCFLAGS_bpf-fancy.o += $(MFLAG)
+HOSTCFLAGS_user-trap.o += $(MFLAG)
 HOSTLDLIBS_bpf-direct += $(MFLAG)
 HOSTLDLIBS_bpf-fancy += $(MFLAG)
 HOSTLDLIBS_dropper += $(MFLAG)
index 525bff6..3081603 100644 (file)
@@ -23,10 +23,6 @@ depfile = $(subst $(comma),_,$(dot-target).d)
 # filename of target with directory and extension stripped
 basetarget = $(basename $(notdir $@))
 
-###
-# filename of first prerequisite with directory and extension stripped
-baseprereq = $(basename $(notdir $<))
-
 ###
 # Escape single quote for use in echo statements
 escsq = $(subst $(squote),'\$(squote)',$1)
index 408ee38..18fedf7 100644 (file)
@@ -32,7 +32,7 @@ type T;
   (T *)
   \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
    kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
-   dma_alloc_coherent\|dma_zalloc_coherent\|devm_kmalloc\|devm_kzalloc\|
+   dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
    kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
    pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
    kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
@@ -55,7 +55,7 @@ type r1.T;
 * (T *)
   \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
    kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
-   dma_alloc_coherent\|dma_zalloc_coherent\|devm_kmalloc\|devm_kzalloc\|
+   dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
    kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
    pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
    kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
@@ -78,7 +78,7 @@ type r1.T;
 - (T *)
   \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
    kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
-   dma_alloc_coherent\|dma_zalloc_coherent\|devm_kmalloc\|devm_kzalloc\|
+   dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
    kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
    pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
    kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
@@ -95,7 +95,7 @@ position p;
  (T@p *)
   \(kmalloc\|kzalloc\|kcalloc\|kmem_cache_alloc\|kmem_cache_zalloc\|
    kmem_cache_alloc_node\|kmalloc_node\|kzalloc_node\|vmalloc\|vzalloc\|
-   dma_alloc_coherent\|dma_zalloc_coherent\|devm_kmalloc\|devm_kzalloc\|
+   dma_alloc_coherent\|devm_kmalloc\|devm_kzalloc\|
    kvmalloc\|kvzalloc\|kvmalloc_node\|kvzalloc_node\|pci_alloc_consistent\|
    pci_zalloc_consistent\|kmem_alloc\|kmem_zalloc\|kmem_zone_alloc\|
    kmem_zone_zalloc\|vmalloc_node\|vzalloc_node\)(...)
index d819275..5cd1991 100644 (file)
@@ -69,15 +69,6 @@ statement S;
 - x = (T)vmalloc(E1);
 + x = (T)vzalloc(E1);
 |
-- x = dma_alloc_coherent(E2,E1,E3,E4);
-+ x = dma_zalloc_coherent(E2,E1,E3,E4);
-|
-- x = (T *)dma_alloc_coherent(E2,E1,E3,E4);
-+ x = dma_zalloc_coherent(E2,E1,E3,E4);
-|
-- x = (T)dma_alloc_coherent(E2,E1,E3,E4);
-+ x = (T)dma_zalloc_coherent(E2,E1,E3,E4);
-|
 - x = kmalloc_node(E1,E2,E3);
 + x = kzalloc_node(E1,E2,E3);
 |
@@ -225,7 +216,7 @@ p << r2.p;
 x << r2.x;
 @@
 
-msg="WARNING: dma_zalloc_coherent should be used for %s, instead of dma_alloc_coherent/memset" % (x)
+msg="WARNING: dma_alloc_coherent use in %s already zeroes out memory,  so memset is not needed" % (x)
 coccilib.report.print_report(p[0], msg)
 
 //-----------------------------------------------------------------
index de70b84..89c47f5 100644 (file)
@@ -13,7 +13,7 @@ static unsigned int arm_pertask_ssp_rtl_execute(void)
        for (insn = get_insns(); insn; insn = NEXT_INSN(insn)) {
                const char *sym;
                rtx body;
-               rtx masked_sp;
+               rtx mask, masked_sp;
 
                /*
                 * Find a SET insn involving a SYMBOL_REF to __stack_chk_guard
@@ -33,12 +33,13 @@ static unsigned int arm_pertask_ssp_rtl_execute(void)
                 * produces the address of the copy of the stack canary value
                 * stored in struct thread_info
                 */
+               mask = GEN_INT(sext_hwi(sp_mask, GET_MODE_PRECISION(Pmode)));
                masked_sp = gen_reg_rtx(Pmode);
 
                emit_insn_before(gen_rtx_SET(masked_sp,
                                             gen_rtx_AND(Pmode,
                                                         stack_pointer_rtx,
-                                                        GEN_INT(sp_mask))),
+                                                        mask)),
                                 insn);
 
                SET_SRC(body) = gen_rtx_PLUS(Pmode, masked_sp,
@@ -52,6 +53,19 @@ static unsigned int arm_pertask_ssp_rtl_execute(void)
 #define NO_GATE
 #include "gcc-generate-rtl-pass.h"
 
+#if BUILDING_GCC_VERSION >= 9000
+static bool no(void)
+{
+       return false;
+}
+
+static void arm_pertask_ssp_start_unit(void *gcc_data, void *user_data)
+{
+       targetm.have_stack_protect_combined_set = no;
+       targetm.have_stack_protect_combined_test = no;
+}
+#endif
+
 __visible int plugin_init(struct plugin_name_args *plugin_info,
                          struct plugin_gcc_version *version)
 {
@@ -99,5 +113,10 @@ __visible int plugin_init(struct plugin_name_args *plugin_info,
        register_callback(plugin_info->base_name, PLUGIN_PASS_MANAGER_SETUP,
                          NULL, &arm_pertask_ssp_rtl_pass_info);
 
+#if BUILDING_GCC_VERSION >= 9000
+       register_callback(plugin_info->base_name, PLUGIN_START_UNIT,
+                         arm_pertask_ssp_start_unit, NULL);
+#endif
+
        return 0;
 }
index 77cebad..f75e7bd 100644 (file)
@@ -118,8 +118,8 @@ static int read_symbol(FILE *in, struct sym_entry *s)
                        fprintf(stderr, "Read error or end of file.\n");
                return -1;
        }
-       if (strlen(sym) > KSYM_NAME_LEN) {
-               fprintf(stderr, "Symbol %s too long for kallsyms (%zu vs %d).\n"
+       if (strlen(sym) >= KSYM_NAME_LEN) {
+               fprintf(stderr, "Symbol %s too long for kallsyms (%zu >= %d).\n"
                                "Please increase KSYM_NAME_LEN both in kernel and kallsyms.c\n",
                        sym, strlen(sym), KSYM_NAME_LEN);
                return -1;
index c05ab00..1819735 100644 (file)
@@ -206,4 +206,4 @@ filechk_conf_cfg = $(CONFIG_SHELL) $<
 $(obj)/%conf-cfg: $(src)/%conf-cfg.sh FORCE
        $(call filechk,conf_cfg)
 
-clean-files += conf-cfg
+clean-files += *conf-cfg
index 0de2fb2..26bf886 100644 (file)
@@ -2185,7 +2185,7 @@ static void add_intree_flag(struct buffer *b, int is_intree)
 /* Cannot check for assembler */
 static void add_retpoline(struct buffer *b)
 {
-       buf_printf(b, "\n#ifdef RETPOLINE\n");
+       buf_printf(b, "\n#ifdef CONFIG_RETPOLINE\n");
        buf_printf(b, "MODULE_INFO(retpoline, \"Y\");\n");
        buf_printf(b, "#endif\n");
 }
index 08c88de..11975ec 100644 (file)
@@ -1444,7 +1444,10 @@ check:
                        new = aa_label_merge(label, target, GFP_KERNEL);
                if (IS_ERR_OR_NULL(new)) {
                        info = "failed to build target label";
-                       error = PTR_ERR(new);
+                       if (!new)
+                               error = -ENOMEM;
+                       else
+                               error = PTR_ERR(new);
                        new = NULL;
                        perms.allow = 0;
                        goto audit;
index 2c01087..8db1731 100644 (file)
@@ -1599,12 +1599,14 @@ static unsigned int apparmor_ipv4_postroute(void *priv,
        return apparmor_ip_postroute(priv, skb, state);
 }
 
+#if IS_ENABLED(CONFIG_IPV6)
 static unsigned int apparmor_ipv6_postroute(void *priv,
                                            struct sk_buff *skb,
                                            const struct nf_hook_state *state)
 {
        return apparmor_ip_postroute(priv, skb, state);
 }
+#endif
 
 static const struct nf_hook_ops apparmor_nf_ops[] = {
        {
index 479909b..8f533c8 100644 (file)
@@ -186,20 +186,9 @@ static inline int key_permission(const key_ref_t key_ref, unsigned perm)
        return key_task_permission(key_ref, current_cred(), perm);
 }
 
-/*
- * Authorisation record for request_key().
- */
-struct request_key_auth {
-       struct key              *target_key;
-       struct key              *dest_keyring;
-       const struct cred       *cred;
-       void                    *callout_info;
-       size_t                  callout_len;
-       pid_t                   pid;
-} __randomize_layout;
-
 extern struct key_type key_type_request_key_auth;
 extern struct key *request_key_auth_new(struct key *target,
+                                       const char *op,
                                        const void *callout_info,
                                        size_t callout_len,
                                        struct key *dest_keyring);
index 44a80d6..696f1c0 100644 (file)
@@ -265,8 +265,8 @@ struct key *key_alloc(struct key_type *type, const char *desc,
 
                spin_lock(&user->lock);
                if (!(flags & KEY_ALLOC_QUOTA_OVERRUN)) {
-                       if (user->qnkeys + 1 >= maxkeys ||
-                           user->qnbytes + quotalen >= maxbytes ||
+                       if (user->qnkeys + 1 > maxkeys ||
+                           user->qnbytes + quotalen > maxbytes ||
                            user->qnbytes + quotalen < user->qnbytes)
                                goto no_quota;
                }
@@ -297,6 +297,7 @@ struct key *key_alloc(struct key_type *type, const char *desc,
        key->gid = gid;
        key->perm = perm;
        key->restrict_link = restrict_link;
+       key->last_used_at = ktime_get_real_seconds();
 
        if (!(flags & KEY_ALLOC_NOT_IN_QUOTA))
                key->flags |= 1 << KEY_FLAG_IN_QUOTA;
index e8093d0..7bbe035 100644 (file)
@@ -25,6 +25,7 @@
 #include <linux/security.h>
 #include <linux/uio.h>
 #include <linux/uaccess.h>
+#include <keys/request_key_auth-type.h>
 #include "internal.h"
 
 #define KEY_MAX_DESC_SIZE 4096
index eadebb9..f81372f 100644 (file)
@@ -661,9 +661,6 @@ static bool search_nested_keyrings(struct key *keyring,
        BUG_ON((ctx->flags & STATE_CHECKS) == 0 ||
               (ctx->flags & STATE_CHECKS) == STATE_CHECKS);
 
-       if (ctx->index_key.description)
-               ctx->index_key.desc_len = strlen(ctx->index_key.description);
-
        /* Check to see if this top-level keyring is what we are looking for
         * and whether it is valid or not.
         */
@@ -914,6 +911,7 @@ key_ref_t keyring_search(key_ref_t keyring,
        struct keyring_search_context ctx = {
                .index_key.type         = type,
                .index_key.description  = description,
+               .index_key.desc_len     = strlen(description),
                .cred                   = current_cred(),
                .match_data.cmp         = key_default_cmp,
                .match_data.raw_data    = description,
index d2b8020..78ac305 100644 (file)
@@ -165,8 +165,7 @@ static int proc_keys_show(struct seq_file *m, void *v)
        int rc;
 
        struct keyring_search_context ctx = {
-               .index_key.type         = key->type,
-               .index_key.description  = key->description,
+               .index_key              = key->index_key,
                .cred                   = m->file->f_cred,
                .match_data.cmp         = lookup_user_key_possessed,
                .match_data.raw_data    = key,
index 02c77e9..0e0b9cc 100644 (file)
@@ -19,6 +19,7 @@
 #include <linux/security.h>
 #include <linux/user_namespace.h>
 #include <linux/uaccess.h>
+#include <keys/request_key_auth-type.h>
 #include "internal.h"
 
 /* Session keyring create vs join semaphore */
index 301f0e3..7a0c6b6 100644 (file)
 #include <linux/keyctl.h>
 #include <linux/slab.h>
 #include "internal.h"
+#include <keys/request_key_auth-type.h>
 
 #define key_negative_timeout   60      /* default timeout on a negative key's existence */
 
 /**
  * complete_request_key - Complete the construction of a key.
- * @cons: The key construction record.
+ * @auth_key: The authorisation key.
  * @error: The success or failute of the construction.
  *
  * Complete the attempt to construct a key.  The key will be negated
  * if an error is indicated.  The authorisation key will be revoked
  * unconditionally.
  */
-void complete_request_key(struct key_construction *cons, int error)
+void complete_request_key(struct key *authkey, int error)
 {
-       kenter("{%d,%d},%d", cons->key->serial, cons->authkey->serial, error);
+       struct request_key_auth *rka = get_request_key_auth(authkey);
+       struct key *key = rka->target_key;
+
+       kenter("%d{%d},%d", authkey->serial, key->serial, error);
 
        if (error < 0)
-               key_negate_and_link(cons->key, key_negative_timeout, NULL,
-                                   cons->authkey);
+               key_negate_and_link(key, key_negative_timeout, NULL, authkey);
        else
-               key_revoke(cons->authkey);
-
-       key_put(cons->key);
-       key_put(cons->authkey);
-       kfree(cons);
+               key_revoke(authkey);
 }
 EXPORT_SYMBOL(complete_request_key);
 
@@ -91,21 +90,19 @@ static int call_usermodehelper_keys(const char *path, char **argv, char **envp,
  * Request userspace finish the construction of a key
  * - execute "/sbin/request-key <op> <key> <uid> <gid> <keyring> <keyring> <keyring>"
  */
-static int call_sbin_request_key(struct key_construction *cons,
-                                const char *op,
-                                void *aux)
+static int call_sbin_request_key(struct key *authkey, void *aux)
 {
        static char const request_key[] = "/sbin/request-key";
+       struct request_key_auth *rka = get_request_key_auth(authkey);
        const struct cred *cred = current_cred();
        key_serial_t prkey, sskey;
-       struct key *key = cons->key, *authkey = cons->authkey, *keyring,
-               *session;
+       struct key *key = rka->target_key, *keyring, *session;
        char *argv[9], *envp[3], uid_str[12], gid_str[12];
        char key_str[12], keyring_str[3][12];
        char desc[20];
        int ret, i;
 
-       kenter("{%d},{%d},%s", key->serial, authkey->serial, op);
+       kenter("{%d},{%d},%s", key->serial, authkey->serial, rka->op);
 
        ret = install_user_keyrings();
        if (ret < 0)
@@ -163,7 +160,7 @@ static int call_sbin_request_key(struct key_construction *cons,
        /* set up the argument list */
        i = 0;
        argv[i++] = (char *)request_key;
-       argv[i++] = (char *) op;
+       argv[i++] = (char *)rka->op;
        argv[i++] = key_str;
        argv[i++] = uid_str;
        argv[i++] = gid_str;
@@ -191,7 +188,7 @@ error_link:
        key_put(keyring);
 
 error_alloc:
-       complete_request_key(cons, ret);
+       complete_request_key(authkey, ret);
        kleave(" = %d", ret);
        return ret;
 }
@@ -205,42 +202,31 @@ static int construct_key(struct key *key, const void *callout_info,
                         size_t callout_len, void *aux,
                         struct key *dest_keyring)
 {
-       struct key_construction *cons;
        request_key_actor_t actor;
        struct key *authkey;
        int ret;
 
        kenter("%d,%p,%zu,%p", key->serial, callout_info, callout_len, aux);
 
-       cons = kmalloc(sizeof(*cons), GFP_KERNEL);
-       if (!cons)
-               return -ENOMEM;
-
        /* allocate an authorisation key */
-       authkey = request_key_auth_new(key, callout_info, callout_len,
+       authkey = request_key_auth_new(key, "create", callout_info, callout_len,
                                       dest_keyring);
-       if (IS_ERR(authkey)) {
-               kfree(cons);
-               ret = PTR_ERR(authkey);
-               authkey = NULL;
-       } else {
-               cons->authkey = key_get(authkey);
-               cons->key = key_get(key);
+       if (IS_ERR(authkey))
+               return PTR_ERR(authkey);
 
-               /* make the call */
-               actor = call_sbin_request_key;
-               if (key->type->request_key)
-                       actor = key->type->request_key;
+       /* Make the call */
+       actor = call_sbin_request_key;
+       if (key->type->request_key)
+               actor = key->type->request_key;
 
-               ret = actor(cons, "create", aux);
+       ret = actor(authkey, aux);
 
-               /* check that the actor called complete_request_key() prior to
-                * returning an error */
-               WARN_ON(ret < 0 &&
-                       !test_bit(KEY_FLAG_REVOKED, &authkey->flags));
-               key_put(authkey);
-       }
+       /* check that the actor called complete_request_key() prior to
+        * returning an error */
+       WARN_ON(ret < 0 &&
+               !test_bit(KEY_FLAG_REVOKED, &authkey->flags));
 
+       key_put(authkey);
        kleave(" = %d", ret);
        return ret;
 }
@@ -275,7 +261,7 @@ static int construct_get_dest_keyring(struct key **_dest_keyring)
                        if (cred->request_key_auth) {
                                authkey = cred->request_key_auth;
                                down_read(&authkey->sem);
-                               rka = authkey->payload.data[0];
+                               rka = get_request_key_auth(authkey);
                                if (!test_bit(KEY_FLAG_REVOKED,
                                              &authkey->flags))
                                        dest_keyring =
@@ -545,6 +531,7 @@ struct key *request_key_and_link(struct key_type *type,
        struct keyring_search_context ctx = {
                .index_key.type         = type,
                .index_key.description  = description,
+               .index_key.desc_len     = strlen(description),
                .cred                   = current_cred(),
                .match_data.cmp         = key_default_cmp,
                .match_data.raw_data    = description,
index 87ea2f5..bda6201 100644 (file)
@@ -17,7 +17,7 @@
 #include <linux/slab.h>
 #include <linux/uaccess.h>
 #include "internal.h"
-#include <keys/user-type.h>
+#include <keys/request_key_auth-type.h>
 
 static int request_key_auth_preparse(struct key_preparsed_payload *);
 static void request_key_auth_free_preparse(struct key_preparsed_payload *);
@@ -68,7 +68,7 @@ static int request_key_auth_instantiate(struct key *key,
 static void request_key_auth_describe(const struct key *key,
                                      struct seq_file *m)
 {
-       struct request_key_auth *rka = key->payload.data[0];
+       struct request_key_auth *rka = get_request_key_auth(key);
 
        seq_puts(m, "key:");
        seq_puts(m, key->description);
@@ -83,7 +83,7 @@ static void request_key_auth_describe(const struct key *key,
 static long request_key_auth_read(const struct key *key,
                                  char __user *buffer, size_t buflen)
 {
-       struct request_key_auth *rka = key->payload.data[0];
+       struct request_key_auth *rka = get_request_key_auth(key);
        size_t datalen;
        long ret;
 
@@ -109,7 +109,7 @@ static long request_key_auth_read(const struct key *key,
  */
 static void request_key_auth_revoke(struct key *key)
 {
-       struct request_key_auth *rka = key->payload.data[0];
+       struct request_key_auth *rka = get_request_key_auth(key);
 
        kenter("{%d}", key->serial);
 
@@ -136,7 +136,7 @@ static void free_request_key_auth(struct request_key_auth *rka)
  */
 static void request_key_auth_destroy(struct key *key)
 {
-       struct request_key_auth *rka = key->payload.data[0];
+       struct request_key_auth *rka = get_request_key_auth(key);
 
        kenter("{%d}", key->serial);
 
@@ -147,8 +147,9 @@ static void request_key_auth_destroy(struct key *key)
  * Create an authorisation token for /sbin/request-key or whoever to gain
  * access to the caller's security data.
  */
-struct key *request_key_auth_new(struct key *target, const void *callout_info,
-                                size_t callout_len, struct key *dest_keyring)
+struct key *request_key_auth_new(struct key *target, const char *op,
+                                const void *callout_info, size_t callout_len,
+                                struct key *dest_keyring)
 {
        struct request_key_auth *rka, *irka;
        const struct cred *cred = current->cred;
@@ -166,6 +167,7 @@ struct key *request_key_auth_new(struct key *target, const void *callout_info,
        if (!rka->callout_info)
                goto error_free_rka;
        rka->callout_len = callout_len;
+       strlcpy(rka->op, op, sizeof(rka->op));
 
        /* see if the calling process is already servicing the key request of
         * another process */
@@ -245,7 +247,7 @@ struct key *key_get_instantiation_authkey(key_serial_t target_id)
        struct key *authkey;
        key_ref_t authkey_ref;
 
-       sprintf(description, "%x", target_id);
+       ctx.index_key.desc_len = sprintf(description, "%x", target_id);
 
        authkey_ref = search_process_keyrings(&ctx);
 
index f840010..33028c0 100644 (file)
@@ -321,6 +321,7 @@ static void dump_common_audit_data(struct audit_buffer *ab,
                if (a->u.net->sk) {
                        struct sock *sk = a->u.net->sk;
                        struct unix_sock *u;
+                       struct unix_address *addr;
                        int len = 0;
                        char *p = NULL;
 
@@ -351,14 +352,15 @@ static void dump_common_audit_data(struct audit_buffer *ab,
 #endif
                        case AF_UNIX:
                                u = unix_sk(sk);
+                               addr = smp_load_acquire(&u->addr);
+                               if (!addr)
+                                       break;
                                if (u->path.dentry) {
                                        audit_log_d_path(ab, " path=", &u->path);
                                        break;
                                }
-                               if (!u->addr)
-                                       break;
-                               len = u->addr->len-sizeof(short);
-                               p = &u->addr->name->sun_path[0];
+                               len = addr->len-sizeof(short);
+                               p = &addr->name->sun_path[0];
                                audit_log_format(ab, " path=");
                                if (*p)
                                        audit_log_untrustedstring(ab, p);
index f1b8d25..55bc490 100644 (file)
@@ -1027,6 +1027,13 @@ int security_cred_alloc_blank(struct cred *cred, gfp_t gfp)
 
 void security_cred_free(struct cred *cred)
 {
+       /*
+        * There is a failure case in prepare_creds() that
+        * may result in a call here with ->security being NULL.
+        */
+       if (unlikely(cred->security == NULL))
+               return;
+
        call_void_hook(cred_free, cred);
 }
 
index a50d625..c1c31e3 100644 (file)
@@ -732,7 +732,8 @@ static int sens_destroy(void *key, void *datum, void *p)
        kfree(key);
        if (datum) {
                levdatum = datum;
-               ebitmap_destroy(&levdatum->level->cat);
+               if (levdatum->level)
+                       ebitmap_destroy(&levdatum->level->cat);
                kfree(levdatum->level);
        }
        kfree(datum);
index ffda91a..02514fe 100644 (file)
@@ -368,7 +368,9 @@ static int yama_ptrace_access_check(struct task_struct *child,
                        break;
                case YAMA_SCOPE_RELATIONAL:
                        rcu_read_lock();
-                       if (!task_is_descendant(current, child) &&
+                       if (!pid_alive(child))
+                               rc = -EPERM;
+                       if (!rc && !task_is_descendant(current, child) &&
                            !ptracer_exception_found(current, child) &&
                            !ns_capable(__task_cred(child)->user_ns, CAP_SYS_PTRACE))
                                rc = -EPERM;
index c3f57a3..40ebde2 100644 (file)
@@ -47,8 +47,8 @@ static int alloc_dbdma_descriptor_ring(struct i2sbus_dev *i2sdev,
        /* We use the PCI APIs for now until the generic one gets fixed
         * enough or until we get some macio-specific versions
         */
-       r->space = dma_zalloc_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
-                                      r->size, &r->bus_addr, GFP_KERNEL);
+       r->space = dma_alloc_coherent(&macio_get_pci_dev(i2sdev->macio)->dev,
+                                     r->size, &r->bus_addr, GFP_KERNEL);
        if (!r->space)
                return -ENOMEM;
 
index a5b09e7..f7d2b37 100644 (file)
@@ -541,7 +541,8 @@ static int snd_compress_check_input(struct snd_compr_params *params)
 {
        /* first let's check the buffer parameter's */
        if (params->buffer.fragment_size == 0 ||
-           params->buffer.fragments > INT_MAX / params->buffer.fragment_size)
+           params->buffer.fragments > INT_MAX / params->buffer.fragment_size ||
+           params->buffer.fragments == 0)
                return -EINVAL;
 
        /* now codec parameters */
index 40013b2..6c0b303 100644 (file)
@@ -2177,16 +2177,11 @@ snd_pcm_sframes_t __snd_pcm_lib_xfer(struct snd_pcm_substream *substream,
                snd_pcm_update_hw_ptr(substream);
 
        if (!is_playback &&
-           runtime->status->state == SNDRV_PCM_STATE_PREPARED) {
-               if (size >= runtime->start_threshold) {
-                       err = snd_pcm_start(substream);
-                       if (err < 0)
-                               goto _end_unlock;
-               } else {
-                       /* nothing to do */
-                       err = 0;
+           runtime->status->state == SNDRV_PCM_STATE_PREPARED &&
+           size >= runtime->start_threshold) {
+               err = snd_pcm_start(substream);
+               if (err < 0)
                        goto _end_unlock;
-               }
        }
 
        avail = snd_pcm_avail(substream);
index 598d140..5fc497c 100644 (file)
@@ -903,6 +903,9 @@ int cs46xx_dsp_proc_done (struct snd_cs46xx *chip)
        struct dsp_spos_instance * ins = chip->dsp_spos_instance;
        int i;
 
+       if (!ins)
+               return 0;
+
        snd_info_free_entry(ins->proc_sym_info_entry);
        ins->proc_sym_info_entry = NULL;
 
index 9174f1b..1ec706c 100644 (file)
@@ -115,7 +115,8 @@ static int hda_codec_driver_probe(struct device *dev)
        err = snd_hda_codec_build_controls(codec);
        if (err < 0)
                goto error_module;
-       if (codec->card->registered) {
+       /* only register after the bus probe finished; otherwise it's racy */
+       if (!codec->bus->bus_probing && codec->card->registered) {
                err = snd_card_register(codec->card);
                if (err < 0)
                        goto error_module;
index e784130..e5c4900 100644 (file)
@@ -2185,6 +2185,7 @@ static int azx_probe_continue(struct azx *chip)
        int dev = chip->dev_index;
        int err;
 
+       to_hda_bus(bus)->bus_probing = 1;
        hda->probe_continued = 1;
 
        /* bind with i915 if needed */
@@ -2269,6 +2270,7 @@ out_free:
        if (err < 0)
                hda->init_failed = 1;
        complete_all(&hda->probe_wait);
+       to_hda_bus(bus)->bus_probing = 0;
        return err;
 }
 
index e5bdbc2..29882bd 100644 (file)
@@ -8451,8 +8451,10 @@ static void ca0132_free(struct hda_codec *codec)
        ca0132_exit_chip(codec);
 
        snd_hda_power_down(codec);
-       if (IS_ENABLED(CONFIG_PCI) && spec->mem_base)
+#ifdef CONFIG_PCI
+       if (spec->mem_base)
                pci_iounmap(codec->bus->pci, spec->mem_base);
+#endif
        kfree(spec->spec_init_verbs);
        kfree(codec->spec);
 }
index 51cc658..a4ee765 100644 (file)
@@ -924,6 +924,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x103c, 0x807C, "HP EliteBook 820 G3", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x80FD, "HP ProBook 640 G2", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x828c, "HP EliteBook 840 G4", CXT_FIXUP_HP_DOCK),
+       SND_PCI_QUIRK(0x103c, 0x83b2, "HP EliteBook 840 G5", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x83b3, "HP EliteBook 830 G5", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x83d3, "HP ProBook 640 G4", CXT_FIXUP_HP_DOCK),
        SND_PCI_QUIRK(0x103c, 0x8174, "HP Spectre x360", CXT_FIXUP_HP_SPECTRE),
@@ -931,6 +932,7 @@ static const struct snd_pci_quirk cxt5066_fixups[] = {
        SND_PCI_QUIRK(0x103c, 0x814f, "HP ZBook 15u G3", CXT_FIXUP_MUTE_LED_GPIO),
        SND_PCI_QUIRK(0x103c, 0x822e, "HP ProBook 440 G4", CXT_FIXUP_MUTE_LED_GPIO),
        SND_PCI_QUIRK(0x103c, 0x836e, "HP ProBook 455 G5", CXT_FIXUP_MUTE_LED_GPIO),
+       SND_PCI_QUIRK(0x103c, 0x837f, "HP ProBook 470 G5", CXT_FIXUP_MUTE_LED_GPIO),
        SND_PCI_QUIRK(0x103c, 0x8299, "HP 800 G3 SFF", CXT_FIXUP_HP_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x829a, "HP 800 G3 DM", CXT_FIXUP_HP_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x8455, "HP Z2 G4", CXT_FIXUP_HP_MIC_NO_PRESENCE),
index aee4cbd..1ffa36e 100644 (file)
@@ -117,6 +117,7 @@ struct alc_spec {
        int codec_variant;      /* flag for other variants */
        unsigned int has_alc5505_dsp:1;
        unsigned int no_depop_delay:1;
+       unsigned int done_hp_init:1;
 
        /* for PLL fix */
        hda_nid_t pll_nid;
@@ -514,6 +515,15 @@ static void alc_auto_init_amp(struct hda_codec *codec, int type)
        }
 }
 
+/* get a primary headphone pin if available */
+static hda_nid_t alc_get_hp_pin(struct alc_spec *spec)
+{
+       if (spec->gen.autocfg.hp_pins[0])
+               return spec->gen.autocfg.hp_pins[0];
+       if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
+               return spec->gen.autocfg.line_out_pins[0];
+       return 0;
+}
 
 /*
  * Realtek SSID verification
@@ -724,9 +734,7 @@ do_sku:
         * 15   : 1 --> enable the function "Mute internal speaker
         *              when the external headphone out jack is plugged"
         */
-       if (!spec->gen.autocfg.hp_pins[0] &&
-           !(spec->gen.autocfg.line_out_pins[0] &&
-             spec->gen.autocfg.line_out_type == AUTO_PIN_HP_OUT)) {
+       if (!alc_get_hp_pin(spec)) {
                hda_nid_t nid;
                tmp = (ass >> 11) & 0x3;        /* HP to chassis */
                nid = ports[tmp];
@@ -1847,6 +1855,8 @@ enum {
        ALC887_FIXUP_BASS_CHMAP,
        ALC1220_FIXUP_GB_DUAL_CODECS,
        ALC1220_FIXUP_CLEVO_P950,
+       ALC1220_FIXUP_SYSTEM76_ORYP5,
+       ALC1220_FIXUP_SYSTEM76_ORYP5_PINS,
 };
 
 static void alc889_fixup_coef(struct hda_codec *codec,
@@ -2048,6 +2058,17 @@ static void alc1220_fixup_clevo_p950(struct hda_codec *codec,
        snd_hda_override_conn_list(codec, 0x1b, 1, conn1);
 }
 
+static void alc_fixup_headset_mode_no_hp_mic(struct hda_codec *codec,
+                               const struct hda_fixup *fix, int action);
+
+static void alc1220_fixup_system76_oryp5(struct hda_codec *codec,
+                                    const struct hda_fixup *fix,
+                                    int action)
+{
+       alc1220_fixup_clevo_p950(codec, fix, action);
+       alc_fixup_headset_mode_no_hp_mic(codec, fix, action);
+}
+
 static const struct hda_fixup alc882_fixups[] = {
        [ALC882_FIXUP_ABIT_AW9D_MAX] = {
                .type = HDA_FIXUP_PINS,
@@ -2292,6 +2313,19 @@ static const struct hda_fixup alc882_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc1220_fixup_clevo_p950,
        },
+       [ALC1220_FIXUP_SYSTEM76_ORYP5] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc1220_fixup_system76_oryp5,
+       },
+       [ALC1220_FIXUP_SYSTEM76_ORYP5_PINS] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x19, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+                       {}
+               },
+               .chained = true,
+               .chain_id = ALC1220_FIXUP_SYSTEM76_ORYP5,
+       },
 };
 
 static const struct snd_pci_quirk alc882_fixup_tbl[] = {
@@ -2368,6 +2402,8 @@ static const struct snd_pci_quirk alc882_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1558, 0x9501, "Clevo P950HR", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1558, 0x95e1, "Clevo P95xER", ALC1220_FIXUP_CLEVO_P950),
        SND_PCI_QUIRK(0x1558, 0x95e2, "Clevo P950ER", ALC1220_FIXUP_CLEVO_P950),
+       SND_PCI_QUIRK(0x1558, 0x96e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_SYSTEM76_ORYP5_PINS),
+       SND_PCI_QUIRK(0x1558, 0x97e1, "System76 Oryx Pro (oryp5)", ALC1220_FIXUP_SYSTEM76_ORYP5_PINS),
        SND_PCI_QUIRK_VENDOR(0x1558, "Clevo laptop", ALC882_FIXUP_EAPD),
        SND_PCI_QUIRK(0x161f, 0x2054, "Medion laptop", ALC883_FIXUP_EAPD),
        SND_PCI_QUIRK(0x17aa, 0x3a0d, "Lenovo Y530", ALC882_FIXUP_LENOVO_Y530),
@@ -2958,7 +2994,7 @@ static void alc282_restore_default_value(struct hda_codec *codec)
 static void alc282_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
        int coef78;
 
@@ -2995,7 +3031,7 @@ static void alc282_init(struct hda_codec *codec)
 static void alc282_shutup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
        int coef78;
 
@@ -3073,14 +3109,9 @@ static void alc283_restore_default_value(struct hda_codec *codec)
 static void alc283_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
-       if (!spec->gen.autocfg.hp_outs) {
-               if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
-                       hp_pin = spec->gen.autocfg.line_out_pins[0];
-       }
-
        alc283_restore_default_value(codec);
 
        if (!hp_pin)
@@ -3114,14 +3145,9 @@ static void alc283_init(struct hda_codec *codec)
 static void alc283_shutup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
-       if (!spec->gen.autocfg.hp_outs) {
-               if (spec->gen.autocfg.line_out_type == AC_JACK_HP_OUT)
-                       hp_pin = spec->gen.autocfg.line_out_pins[0];
-       }
-
        if (!hp_pin) {
                alc269_shutup(codec);
                return;
@@ -3155,7 +3181,7 @@ static void alc283_shutup(struct hda_codec *codec)
 static void alc256_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
        if (!hp_pin)
@@ -3191,7 +3217,7 @@ static void alc256_init(struct hda_codec *codec)
 static void alc256_shutup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
        if (!hp_pin) {
@@ -3227,7 +3253,7 @@ static void alc256_shutup(struct hda_codec *codec)
 static void alc225_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp1_pin_sense, hp2_pin_sense;
 
        if (!hp_pin)
@@ -3270,7 +3296,7 @@ static void alc225_init(struct hda_codec *codec)
 static void alc225_shutup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp1_pin_sense, hp2_pin_sense;
 
        if (!hp_pin) {
@@ -3314,7 +3340,7 @@ static void alc225_shutup(struct hda_codec *codec)
 static void alc_default_init(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
        if (!hp_pin)
@@ -3343,7 +3369,7 @@ static void alc_default_init(struct hda_codec *codec)
 static void alc_default_shutup(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
        bool hp_pin_sense;
 
        if (!hp_pin) {
@@ -3372,6 +3398,48 @@ static void alc_default_shutup(struct hda_codec *codec)
        snd_hda_shutup_pins(codec);
 }
 
+static void alc294_hp_init(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
+       int i, val;
+
+       if (!hp_pin)
+               return;
+
+       snd_hda_codec_write(codec, hp_pin, 0,
+                           AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
+
+       msleep(100);
+
+       snd_hda_codec_write(codec, hp_pin, 0,
+                           AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
+
+       alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */
+       alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */
+
+       /* Wait for depop procedure finish  */
+       val = alc_read_coefex_idx(codec, 0x58, 0x01);
+       for (i = 0; i < 20 && val & 0x0080; i++) {
+               msleep(50);
+               val = alc_read_coefex_idx(codec, 0x58, 0x01);
+       }
+       /* Set HP depop to auto mode */
+       alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b);
+       msleep(50);
+}
+
+static void alc294_init(struct hda_codec *codec)
+{
+       struct alc_spec *spec = codec->spec;
+
+       if (!spec->done_hp_init) {
+               alc294_hp_init(codec);
+               spec->done_hp_init = true;
+       }
+       alc_default_init(codec);
+}
+
 static void alc5505_coef_set(struct hda_codec *codec, unsigned int index_reg,
                             unsigned int val)
 {
@@ -4102,6 +4170,7 @@ static void alc_headset_mode_unplugged(struct hda_codec *codec)
        case 0x10ec0295:
        case 0x10ec0289:
        case 0x10ec0299:
+               alc_process_coef_fw(codec, alc225_pre_hsmode);
                alc_process_coef_fw(codec, coef0225);
                break;
        case 0x10ec0867:
@@ -4736,7 +4805,7 @@ static void alc_update_headset_mode(struct hda_codec *codec)
        struct alc_spec *spec = codec->spec;
 
        hda_nid_t mux_pin = spec->gen.imux_pins[spec->gen.cur_mux[0]];
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
+       hda_nid_t hp_pin = alc_get_hp_pin(spec);
 
        int new_headset_mode;
 
@@ -5015,7 +5084,7 @@ static void alc_fixup_tpt470_dock(struct hda_codec *codec,
 static void alc_shutup_dell_xps13(struct hda_codec *codec)
 {
        struct alc_spec *spec = codec->spec;
-       int hp_pin = spec->gen.autocfg.hp_pins[0];
+       int hp_pin = alc_get_hp_pin(spec);
 
        /* Prevent pop noises when headphones are plugged in */
        snd_hda_codec_write(codec, hp_pin, 0,
@@ -5108,7 +5177,7 @@ static void alc271_hp_gate_mic_jack(struct hda_codec *codec,
 
        if (action == HDA_FIXUP_ACT_PROBE) {
                int mic_pin = find_ext_mic_pin(codec);
-               int hp_pin = spec->gen.autocfg.hp_pins[0];
+               int hp_pin = alc_get_hp_pin(spec);
 
                if (snd_BUG_ON(!mic_pin || !hp_pin))
                        return;
@@ -5440,6 +5509,13 @@ static void alc_fixup_headset_jack(struct hda_codec *codec,
        }
 }
 
+static void alc_fixup_disable_mic_vref(struct hda_codec *codec,
+                                 const struct hda_fixup *fix, int action)
+{
+       if (action == HDA_FIXUP_ACT_PRE_PROBE)
+               snd_hda_codec_set_pin_target(codec, 0x19, PIN_VREFHIZ);
+}
+
 /* for hda_fixup_thinkpad_acpi() */
 #include "thinkpad_helper.c"
 
@@ -5549,6 +5625,7 @@ enum {
        ALC293_FIXUP_LENOVO_SPK_NOISE,
        ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY,
        ALC255_FIXUP_DELL_SPK_NOISE,
+       ALC225_FIXUP_DISABLE_MIC_VREF,
        ALC225_FIXUP_DELL1_MIC_NO_PRESENCE,
        ALC295_FIXUP_DISABLE_DAC3,
        ALC280_FIXUP_HP_HEADSET_MIC,
@@ -5582,6 +5659,8 @@ enum {
        ALC294_FIXUP_ASUS_HEADSET_MIC,
        ALC294_FIXUP_ASUS_SPK,
        ALC225_FIXUP_HEADSET_JACK,
+       ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE,
+       ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE,
 };
 
 static const struct hda_fixup alc269_fixups[] = {
@@ -6268,6 +6347,12 @@ static const struct hda_fixup alc269_fixups[] = {
                .chained = true,
                .chain_id = ALC255_FIXUP_DELL1_MIC_NO_PRESENCE
        },
+       [ALC225_FIXUP_DISABLE_MIC_VREF] = {
+               .type = HDA_FIXUP_FUNC,
+               .v.func = alc_fixup_disable_mic_vref,
+               .chained = true,
+               .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
+       },
        [ALC225_FIXUP_DELL1_MIC_NO_PRESENCE] = {
                .type = HDA_FIXUP_VERBS,
                .v.verbs = (const struct hda_verb[]) {
@@ -6277,7 +6362,7 @@ static const struct hda_fixup alc269_fixups[] = {
                        {}
                },
                .chained = true,
-               .chain_id = ALC269_FIXUP_DELL1_MIC_NO_PRESENCE
+               .chain_id = ALC225_FIXUP_DISABLE_MIC_VREF
        },
        [ALC280_FIXUP_HP_HEADSET_MIC] = {
                .type = HDA_FIXUP_FUNC,
@@ -6522,6 +6607,26 @@ static const struct hda_fixup alc269_fixups[] = {
                .type = HDA_FIXUP_FUNC,
                .v.func = alc_fixup_headset_jack,
        },
+       [ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE] = {
+               .type = HDA_FIXUP_PINS,
+               .v.pins = (const struct hda_pintbl[]) {
+                       { 0x1a, 0x01a1913c }, /* use as headset mic, without its own jack detect */
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC269_FIXUP_HEADSET_MODE_NO_HP_MIC
+       },
+       [ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE] = {
+               .type = HDA_FIXUP_VERBS,
+               .v.verbs = (const struct hda_verb[]) {
+                       /* Disable PCBEEP-IN passthrough */
+                       { 0x20, AC_VERB_SET_COEF_INDEX, 0x36 },
+                       { 0x20, AC_VERB_SET_PROC_COEF, 0x57d7 },
+                       { }
+               },
+               .chained = true,
+               .chain_id = ALC285_FIXUP_LENOVO_HEADPHONE_NOISE
+       },
 };
 
 static const struct snd_pci_quirk alc269_fixup_tbl[] = {
@@ -6584,6 +6689,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1028, 0x0871, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
        SND_PCI_QUIRK(0x1028, 0x0872, "Dell Precision 3630", ALC255_FIXUP_DELL_HEADSET_MIC),
        SND_PCI_QUIRK(0x1028, 0x0873, "Dell Precision 3930", ALC255_FIXUP_DUMMY_LINEOUT_VERB),
+       SND_PCI_QUIRK(0x1028, 0x0935, "Dell", ALC274_FIXUP_DELL_AIO_LINEOUT_VERB),
        SND_PCI_QUIRK(0x1028, 0x164a, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x1028, 0x164b, "Dell", ALC293_FIXUP_DELL1_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x103c, 0x1586, "HP", ALC269_FIXUP_HP_MUTE_LED_MIC2),
@@ -6699,6 +6805,7 @@ static const struct snd_pci_quirk alc269_fixup_tbl[] = {
        SND_PCI_QUIRK(0x1458, 0xfa53, "Gigabyte BXBT-2807", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb120, "MSI Cubi MS-B120", ALC283_FIXUP_HEADSET_MIC),
        SND_PCI_QUIRK(0x1462, 0xb171, "Cubi N 8GL (MS-B171)", ALC283_FIXUP_HEADSET_MIC),
+       SND_PCI_QUIRK(0x1558, 0x1325, "System76 Darter Pro (darp5)", ALC293_FIXUP_SYSTEM76_MIC_NO_PRESENCE),
        SND_PCI_QUIRK(0x17aa, 0x1036, "Lenovo P520", ALC233_FIXUP_LENOVO_MULTI_CODECS),
        SND_PCI_QUIRK(0x17aa, 0x20f2, "Thinkpad SL410/510", ALC269_FIXUP_SKU_IGNORE),
        SND_PCI_QUIRK(0x17aa, 0x215e, "Thinkpad L512", ALC269_FIXUP_SKU_IGNORE),
@@ -6910,7 +7017,7 @@ static const struct hda_model_fixup alc269_fixup_models[] = {
        {.id = ALC293_FIXUP_LENOVO_SPK_NOISE, .name = "lenovo-spk-noise"},
        {.id = ALC233_FIXUP_LENOVO_LINE2_MIC_HOTKEY, .name = "lenovo-hotkey"},
        {.id = ALC255_FIXUP_DELL_SPK_NOISE, .name = "dell-spk-noise"},
-       {.id = ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc255-dell1"},
+       {.id = ALC225_FIXUP_DELL1_MIC_NO_PRESENCE, .name = "alc225-dell1"},
        {.id = ALC295_FIXUP_DISABLE_DAC3, .name = "alc295-disable-dac3"},
        {.id = ALC280_FIXUP_HP_HEADSET_MIC, .name = "alc280-hp-headset"},
        {.id = ALC221_FIXUP_HP_FRONT_MIC, .name = "alc221-hp-mic"},
@@ -7205,7 +7312,7 @@ static const struct snd_hda_pin_quirk alc269_pin_fixup_tbl[] = {
                {0x12, 0x90a60130},
                {0x19, 0x03a11020},
                {0x21, 0x0321101f}),
-       SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_LENOVO_HEADPHONE_NOISE,
+       SND_HDA_PIN_QUIRK(0x10ec0285, 0x17aa, "Lenovo", ALC285_FIXUP_LENOVO_PC_BEEP_IN_NOISE,
                {0x12, 0x90a60130},
                {0x14, 0x90170110},
                {0x19, 0x04a11040},
@@ -7357,37 +7464,6 @@ static void alc269_fill_coef(struct hda_codec *codec)
        alc_update_coef_idx(codec, 0x4, 0, 1<<11);
 }
 
-static void alc294_hp_init(struct hda_codec *codec)
-{
-       struct alc_spec *spec = codec->spec;
-       hda_nid_t hp_pin = spec->gen.autocfg.hp_pins[0];
-       int i, val;
-
-       if (!hp_pin)
-               return;
-
-       snd_hda_codec_write(codec, hp_pin, 0,
-                           AC_VERB_SET_AMP_GAIN_MUTE, AMP_OUT_MUTE);
-
-       msleep(100);
-
-       snd_hda_codec_write(codec, hp_pin, 0,
-                           AC_VERB_SET_PIN_WIDGET_CONTROL, 0x0);
-
-       alc_update_coef_idx(codec, 0x6f, 0x000f, 0);/* Set HP depop to manual mode */
-       alc_update_coefex_idx(codec, 0x58, 0x00, 0x8000, 0x8000); /* HP depop procedure start */
-
-       /* Wait for depop procedure finish  */
-       val = alc_read_coefex_idx(codec, 0x58, 0x01);
-       for (i = 0; i < 20 && val & 0x0080; i++) {
-               msleep(50);
-               val = alc_read_coefex_idx(codec, 0x58, 0x01);
-       }
-       /* Set HP depop to auto mode */
-       alc_update_coef_idx(codec, 0x6f, 0x000f, 0x000b);
-       msleep(50);
-}
-
 /*
  */
 static int patch_alc269(struct hda_codec *codec)
@@ -7513,7 +7589,7 @@ static int patch_alc269(struct hda_codec *codec)
                spec->codec_variant = ALC269_TYPE_ALC294;
                spec->gen.mixer_nid = 0; /* ALC2x4 does not have any loopback mixer path */
                alc_update_coef_idx(codec, 0x6b, 0x0018, (1<<4) | (1<<3)); /* UAJ MIC Vref control by verb */
-               alc294_hp_init(codec);
+               spec->init_hook = alc294_init;
                break;
        case 0x10ec0300:
                spec->codec_variant = ALC269_TYPE_ALC300;
@@ -7525,7 +7601,7 @@ static int patch_alc269(struct hda_codec *codec)
                spec->codec_variant = ALC269_TYPE_ALC700;
                spec->gen.mixer_nid = 0; /* ALC700 does not have any loopback mixer path */
                alc_update_coef_idx(codec, 0x4a, 1 << 15, 0); /* Combo jack auto trigger control */
-               alc294_hp_init(codec);
+               spec->init_hook = alc294_init;
                break;
 
        }
index 022a891..3d58338 100644 (file)
@@ -611,14 +611,16 @@ static int acp3x_audio_probe(struct platform_device *pdev)
        }
        irqflags = *((unsigned int *)(pdev->dev.platform_data));
 
-       adata = devm_kzalloc(&pdev->dev, sizeof(struct i2s_dev_data),
-                            GFP_KERNEL);
        res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
        if (!res) {
                dev_err(&pdev->dev, "IORESOURCE_IRQ FAILED\n");
                        return -ENODEV;
        }
 
+       adata = devm_kzalloc(&pdev->dev, sizeof(*adata), GFP_KERNEL);
+       if (!adata)
+               return -ENOMEM;
+
        adata->acp3x_base = devm_ioremap(&pdev->dev, res->start,
                                         resource_size(res));
 
index 3ab2949..b19d7a3 100644 (file)
@@ -1890,51 +1890,31 @@ static void hdmi_codec_remove(struct snd_soc_component *component)
        pm_runtime_disable(&hdev->dev);
 }
 
-#ifdef CONFIG_PM
-static int hdmi_codec_prepare(struct device *dev)
-{
-       struct hdac_device *hdev = dev_to_hdac_dev(dev);
-
-       pm_runtime_get_sync(&hdev->dev);
-
-       /*
-        * Power down afg.
-        * codec_read is preferred over codec_write to set the power state.
-        * This way verb is send to set the power state and response
-        * is received. So setting power state is ensured without using loop
-        * to read the state.
-        */
-       snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE,
-                                                       AC_PWRST_D3);
-
-       return 0;
-}
-
-static void hdmi_codec_complete(struct device *dev)
+#ifdef CONFIG_PM_SLEEP
+static int hdmi_codec_resume(struct device *dev)
 {
        struct hdac_device *hdev = dev_to_hdac_dev(dev);
        struct hdac_hdmi_priv *hdmi = hdev_to_hdmi_priv(hdev);
+       int ret;
 
-       /* Power up afg */
-       snd_hdac_codec_read(hdev, hdev->afg, 0, AC_VERB_SET_POWER_STATE,
-                                                       AC_PWRST_D0);
-
-       hdac_hdmi_skl_enable_all_pins(hdev);
-       hdac_hdmi_skl_enable_dp12(hdev);
-
+       ret = pm_runtime_force_resume(dev);
+       if (ret < 0)
+               return ret;
        /*
         * As the ELD notify callback request is not entertained while the
         * device is in suspend state. Need to manually check detection of
         * all pins here. pin capablity change is not support, so use the
         * already set pin caps.
+        *
+        * NOTE: this is safe to call even if the codec doesn't actually resume.
+        * The pin check involves only with DRM audio component hooks, so it
+        * works even if the HD-audio side is still dreaming peacefully.
         */
        hdac_hdmi_present_sense_all_pins(hdev, hdmi, false);
-
-       pm_runtime_put_sync(&hdev->dev);
+       return 0;
 }
 #else
-#define hdmi_codec_prepare NULL
-#define hdmi_codec_complete NULL
+#define hdmi_codec_resume NULL
 #endif
 
 static const struct snd_soc_component_driver hdmi_hda_codec = {
@@ -2135,75 +2115,6 @@ static int hdac_hdmi_dev_remove(struct hdac_device *hdev)
 }
 
 #ifdef CONFIG_PM
-/*
- * Power management sequences
- * ==========================
- *
- * The following explains the PM handling of HDAC HDMI with its parent
- * device SKL and display power usage
- *
- * Probe
- * -----
- * In SKL probe,
- * 1. skl_probe_work() powers up the display (refcount++ -> 1)
- * 2. enumerates the codecs on the link
- * 3. powers down the display  (refcount-- -> 0)
- *
- * In HDAC HDMI probe,
- * 1. hdac_hdmi_dev_probe() powers up the display (refcount++ -> 1)
- * 2. probe the codec
- * 3. put the HDAC HDMI device to runtime suspend
- * 4. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0)
- *
- * Once children are runtime suspended, SKL device also goes to runtime
- * suspend
- *
- * HDMI Playback
- * -------------
- * Open HDMI device,
- * 1. skl_runtime_resume() invoked
- * 2. hdac_hdmi_runtime_resume() powers up the display (refcount++ -> 1)
- *
- * Close HDMI device,
- * 1. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0)
- * 2. skl_runtime_suspend() invoked
- *
- * S0/S3 Cycle with playback in progress
- * -------------------------------------
- * When the device is opened for playback, the device is runtime active
- * already and the display refcount is 1 as explained above.
- *
- * Entering to S3,
- * 1. hdmi_codec_prepare() invoke the runtime resume of codec which just
- *    increments the PM runtime usage count of the codec since the device
- *    is in use already
- * 2. skl_suspend() powers down the display (refcount-- -> 0)
- *
- * Wakeup from S3,
- * 1. skl_resume() powers up the display (refcount++ -> 1)
- * 2. hdmi_codec_complete() invokes the runtime suspend of codec which just
- *    decrements the PM runtime usage count of the codec since the device
- *    is in use already
- *
- * Once playback is stopped, the display refcount is set to 0 as explained
- * above in the HDMI playback sequence. The PM handlings are designed in
- * such way that to balance the refcount of display power when the codec
- * device put to S3 while playback is going on.
- *
- * S0/S3 Cycle without playback in progress
- * ----------------------------------------
- * Entering to S3,
- * 1. hdmi_codec_prepare() invoke the runtime resume of codec
- * 2. skl_runtime_resume() invoked
- * 3. hdac_hdmi_runtime_resume() powers up the display (refcount++ -> 1)
- * 4. skl_suspend() powers down the display (refcount-- -> 0)
- *
- * Wakeup from S3,
- * 1. skl_resume() powers up the display (refcount++ -> 1)
- * 2. hdmi_codec_complete() invokes the runtime suspend of codec
- * 3. hdac_hdmi_runtime_suspend() powers down the display (refcount-- -> 0)
- * 4. skl_runtime_suspend() invoked
- */
 static int hdac_hdmi_runtime_suspend(struct device *dev)
 {
        struct hdac_device *hdev = dev_to_hdac_dev(dev);
@@ -2277,8 +2188,7 @@ static int hdac_hdmi_runtime_resume(struct device *dev)
 
 static const struct dev_pm_ops hdac_hdmi_pm = {
        SET_RUNTIME_PM_OPS(hdac_hdmi_runtime_suspend, hdac_hdmi_runtime_resume, NULL)
-       .prepare = hdmi_codec_prepare,
-       .complete = hdmi_codec_complete,
+       SET_SYSTEM_SLEEP_PM_OPS(pm_runtime_force_suspend, hdmi_codec_resume)
 };
 
 static const struct hda_device_id hdmi_list[] = {
index d00734d..e5b6769 100644 (file)
@@ -795,6 +795,8 @@ static int hdmi_codec_probe(struct platform_device *pdev)
        if (hcd->spdif)
                hcp->daidrv[i] = hdmi_spdif_dai;
 
+       dev_set_drvdata(dev, hcp);
+
        ret = devm_snd_soc_register_component(dev, &hdmi_driver, hcp->daidrv,
                                     dai_count);
        if (ret) {
@@ -802,8 +804,6 @@ static int hdmi_codec_probe(struct platform_device *pdev)
                        __func__, ret);
                return ret;
        }
-
-       dev_set_drvdata(dev, hcp);
        return 0;
 }
 
index 6cb1653..4cc24a5 100644 (file)
@@ -1400,24 +1400,20 @@ static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
                if (ret != 0) {
                        dev_err(component->dev,
                                "Failed to set digital mute: %d\n", ret);
-                       mutex_unlock(&pcm512x->mutex);
-                       return ret;
+                       goto unlock;
                }
 
                regmap_read_poll_timeout(pcm512x->regmap,
                                         PCM512x_ANALOG_MUTE_DET,
                                         mute_det, (mute_det & 0x3) == 0,
                                         200, 10000);
-
-               mutex_unlock(&pcm512x->mutex);
        } else {
                pcm512x->mute &= ~0x1;
                ret = pcm512x_update_mute(pcm512x);
                if (ret != 0) {
                        dev_err(component->dev,
                                "Failed to update digital mute: %d\n", ret);
-                       mutex_unlock(&pcm512x->mutex);
-                       return ret;
+                       goto unlock;
                }
 
                regmap_read_poll_timeout(pcm512x->regmap,
@@ -1428,9 +1424,10 @@ static int pcm512x_digital_mute(struct snd_soc_dai *dai, int mute)
                                         200, 10000);
        }
 
+unlock:
        mutex_unlock(&pcm512x->mutex);
 
-       return 0;
+       return ret;
 }
 
 static const struct snd_soc_dai_ops pcm512x_dai_ops = {
index 0ef966d..e2855ab 100644 (file)
@@ -1128,8 +1128,11 @@ static int rt274_i2c_probe(struct i2c_client *i2c,
                return ret;
        }
 
-       regmap_read(rt274->regmap,
+       ret = regmap_read(rt274->regmap,
                RT274_GET_PARAM(AC_NODE_ROOT, AC_PAR_VENDOR_ID), &val);
+       if (ret)
+               return ret;
+
        if (val != RT274_VENDOR_ID) {
                dev_err(&i2c->dev,
                        "Device with ID register %#x is not rt274\n", val);
index 4d46f45..bec2eef 100644 (file)
@@ -280,6 +280,8 @@ static int rt5514_spi_pcm_probe(struct snd_soc_component *component)
 
        rt5514_dsp = devm_kzalloc(component->dev, sizeof(*rt5514_dsp),
                        GFP_KERNEL);
+       if (!rt5514_dsp)
+               return -ENOMEM;
 
        rt5514_dsp->dev = &rt5514_spi->dev;
        mutex_init(&rt5514_dsp->dma_lock);
index 34cfaf8..a9b91bc 100644 (file)
@@ -1778,7 +1778,9 @@ static const struct snd_soc_dapm_route rt5682_dapm_routes[] = {
        {"ADC Stereo1 Filter", NULL, "ADC STO1 ASRC", is_using_asrc},
        {"DAC Stereo1 Filter", NULL, "DAC STO1 ASRC", is_using_asrc},
        {"ADC STO1 ASRC", NULL, "AD ASRC"},
+       {"ADC STO1 ASRC", NULL, "DA ASRC"},
        {"ADC STO1 ASRC", NULL, "CLKDET"},
+       {"DAC STO1 ASRC", NULL, "AD ASRC"},
        {"DAC STO1 ASRC", NULL, "DA ASRC"},
        {"DAC STO1 ASRC", NULL, "CLKDET"},
 
@@ -2512,6 +2514,7 @@ static void rt5682_calibrate(struct rt5682_priv *rt5682)
        regmap_write(rt5682->regmap, RT5682_PWR_DIG_1, 0x0000);
        regmap_write(rt5682->regmap, RT5682_CHOP_DAC, 0x2000);
        regmap_write(rt5682->regmap, RT5682_CALIB_ADC_CTRL, 0x2005);
+       regmap_write(rt5682->regmap, RT5682_STO1_ADC_MIXER, 0xc0c4);
 
        mutex_unlock(&rt5682->calibrate_mutex);
 
index d82a830..96944cf 100644 (file)
 #define RT5682_SCLK_SRC_PLL2                   (0x2 << 13)
 #define RT5682_SCLK_SRC_SDW                    (0x3 << 13)
 #define RT5682_SCLK_SRC_RCCLK                  (0x4 << 13)
-#define RT5682_PLL1_SRC_MASK                   (0x3 << 10)
-#define RT5682_PLL1_SRC_SFT                    10
-#define RT5682_PLL1_SRC_MCLK                   (0x0 << 10)
-#define RT5682_PLL1_SRC_BCLK1                  (0x1 << 10)
-#define RT5682_PLL1_SRC_SDW                    (0x2 << 10)
-#define RT5682_PLL1_SRC_RC                     (0x3 << 10)
-#define RT5682_PLL2_SRC_MASK                   (0x3 << 8)
-#define RT5682_PLL2_SRC_SFT                    8
-#define RT5682_PLL2_SRC_MCLK                   (0x0 << 8)
-#define RT5682_PLL2_SRC_BCLK1                  (0x1 << 8)
-#define RT5682_PLL2_SRC_SDW                    (0x2 << 8)
-#define RT5682_PLL2_SRC_RC                     (0x3 << 8)
+#define RT5682_PLL2_SRC_MASK                   (0x3 << 10)
+#define RT5682_PLL2_SRC_SFT                    10
+#define RT5682_PLL2_SRC_MCLK                   (0x0 << 10)
+#define RT5682_PLL2_SRC_BCLK1                  (0x1 << 10)
+#define RT5682_PLL2_SRC_SDW                    (0x2 << 10)
+#define RT5682_PLL2_SRC_RC                     (0x3 << 10)
+#define RT5682_PLL1_SRC_MASK                   (0x3 << 8)
+#define RT5682_PLL1_SRC_SFT                    8
+#define RT5682_PLL1_SRC_MCLK                   (0x0 << 8)
+#define RT5682_PLL1_SRC_BCLK1                  (0x1 << 8)
+#define RT5682_PLL1_SRC_SDW                    (0x2 << 8)
+#define RT5682_PLL1_SRC_RC                     (0x3 << 8)
 
 
 
index e2b5a11..f03195d 100644 (file)
@@ -822,6 +822,10 @@ static int aic32x4_set_bias_level(struct snd_soc_component *component,
        case SND_SOC_BIAS_PREPARE:
                break;
        case SND_SOC_BIAS_STANDBY:
+               /* Initial cold start */
+               if (snd_soc_component_get_bias_level(component) == SND_SOC_BIAS_OFF)
+                       break;
+
                /* Switch off BCLK_N Divider */
                snd_soc_component_update_bits(component, AIC32X4_BCLKN,
                                    AIC32X4_BCLKEN, 0);
index 392d5ee..99e07b0 100644 (file)
@@ -86,49 +86,49 @@ static ssize_t audmux_read_file(struct file *file, char __user *user_buf,
        if (!buf)
                return -ENOMEM;
 
-       ret = snprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
+       ret = scnprintf(buf, PAGE_SIZE, "PDCR: %08x\nPTCR: %08x\n",
                       pdcr, ptcr);
 
        if (ptcr & IMX_AUDMUX_V2_PTCR_TFSDIR)
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                "TxFS output from %s, ",
                                audmux_port_string((ptcr >> 27) & 0x7));
        else
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                "TxFS input, ");
 
        if (ptcr & IMX_AUDMUX_V2_PTCR_TCLKDIR)
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                "TxClk output from %s",
                                audmux_port_string((ptcr >> 22) & 0x7));
        else
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                "TxClk input");
 
-       ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+       ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
 
        if (ptcr & IMX_AUDMUX_V2_PTCR_SYN) {
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                "Port is symmetric");
        } else {
                if (ptcr & IMX_AUDMUX_V2_PTCR_RFSDIR)
-                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                        "RxFS output from %s, ",
                                        audmux_port_string((ptcr >> 17) & 0x7));
                else
-                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                        "RxFS input, ");
 
                if (ptcr & IMX_AUDMUX_V2_PTCR_RCLKDIR)
-                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                        "RxClk output from %s",
                                        audmux_port_string((ptcr >> 12) & 0x7));
                else
-                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                        "RxClk input");
        }
 
-       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                        "\nData received from %s\n",
                        audmux_port_string((pdcr >> 13) & 0x7));
 
index 37e001c..3fe3441 100644 (file)
@@ -462,7 +462,7 @@ static int asoc_simple_card_parse_of(struct simple_card_data *priv)
        conf_idx        = 0;
        node = of_get_child_by_name(top, PREFIX "dai-link");
        if (!node) {
-               node = dev->of_node;
+               node = of_node_get(top);
                loop = 0;
        }
 
index 99a62ba..bd9fd20 100644 (file)
@@ -91,7 +91,7 @@ config SND_SST_ATOM_HIFI2_PLATFORM_PCI
 config SND_SST_ATOM_HIFI2_PLATFORM_ACPI
        tristate "ACPI HiFi2 (Baytrail, Cherrytrail) Platforms"
        default ACPI
-       depends on X86 && ACPI
+       depends on X86 && ACPI && PCI
        select SND_SST_IPC_ACPI
        select SND_SST_ATOM_HIFI2_PLATFORM
        select SND_SOC_ACPI_INTEL_MATCH
index afc5598..91a2436 100644 (file)
@@ -399,7 +399,13 @@ static int sst_media_hw_params(struct snd_pcm_substream *substream,
                                struct snd_pcm_hw_params *params,
                                struct snd_soc_dai *dai)
 {
-       snd_pcm_lib_malloc_pages(substream, params_buffer_bytes(params));
+       int ret;
+
+       ret =
+               snd_pcm_lib_malloc_pages(substream,
+                               params_buffer_bytes(params));
+       if (ret)
+               return ret;
        memset(substream->runtime->dma_area, 0, params_buffer_bytes(params));
        return 0;
 }
index 68e6543..99f2a01 100644 (file)
@@ -192,7 +192,7 @@ static struct snd_soc_dai_link broadwell_rt286_dais[] = {
                .stream_name = "Loopback",
                .cpu_dai_name = "Loopback Pin",
                .platform_name = "haswell-pcm-audio",
-               .dynamic = 0,
+               .dynamic = 1,
                .codec_name = "snd-soc-dummy",
                .codec_dai_name = "snd-soc-dummy-dai",
                .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
index c74c4f1..8f83b18 100644 (file)
@@ -55,39 +55,6 @@ enum {
        GLK_DPCM_AUDIO_HDMI3_PB,
 };
 
-static int platform_clock_control(struct snd_soc_dapm_widget *w,
-                                       struct snd_kcontrol *k, int  event)
-{
-       struct snd_soc_dapm_context *dapm = w->dapm;
-       struct snd_soc_card *card = dapm->card;
-       struct snd_soc_dai *codec_dai;
-       int ret = 0;
-
-       codec_dai = snd_soc_card_get_codec_dai(card, GLK_REALTEK_CODEC_DAI);
-       if (!codec_dai) {
-               dev_err(card->dev, "Codec dai not found; Unable to set/unset codec pll\n");
-               return -EIO;
-       }
-
-       if (SND_SOC_DAPM_EVENT_OFF(event)) {
-               ret = snd_soc_dai_set_sysclk(codec_dai, 0, 0, 0);
-               if (ret)
-                       dev_err(card->dev, "failed to stop sysclk: %d\n", ret);
-       } else if (SND_SOC_DAPM_EVENT_ON(event)) {
-               ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
-                                       GLK_PLAT_CLK_FREQ, RT5682_PLL_FREQ);
-               if (ret < 0) {
-                       dev_err(card->dev, "can't set codec pll: %d\n", ret);
-                       return ret;
-               }
-       }
-
-       if (ret)
-               dev_err(card->dev, "failed to start internal clk: %d\n", ret);
-
-       return ret;
-}
-
 static const struct snd_kcontrol_new geminilake_controls[] = {
        SOC_DAPM_PIN_SWITCH("Headphone Jack"),
        SOC_DAPM_PIN_SWITCH("Headset Mic"),
@@ -102,14 +69,10 @@ static const struct snd_soc_dapm_widget geminilake_widgets[] = {
        SND_SOC_DAPM_SPK("HDMI1", NULL),
        SND_SOC_DAPM_SPK("HDMI2", NULL),
        SND_SOC_DAPM_SPK("HDMI3", NULL),
-       SND_SOC_DAPM_SUPPLY("Platform Clock", SND_SOC_NOPM, 0, 0,
-                       platform_clock_control, SND_SOC_DAPM_PRE_PMU |
-                       SND_SOC_DAPM_POST_PMD),
 };
 
 static const struct snd_soc_dapm_route geminilake_map[] = {
        /* HP jack connectors - unknown if we have jack detection */
-       { "Headphone Jack", NULL, "Platform Clock" },
        { "Headphone Jack", NULL, "HPOL" },
        { "Headphone Jack", NULL, "HPOR" },
 
@@ -117,7 +80,6 @@ static const struct snd_soc_dapm_route geminilake_map[] = {
        { "Spk", NULL, "Speaker" },
 
        /* other jacks */
-       { "Headset Mic", NULL, "Platform Clock" },
        { "IN1P", NULL, "Headset Mic" },
 
        /* digital mics */
@@ -177,6 +139,13 @@ static int geminilake_rt5682_codec_init(struct snd_soc_pcm_runtime *rtd)
        struct snd_soc_jack *jack;
        int ret;
 
+       ret = snd_soc_dai_set_pll(codec_dai, 0, RT5682_PLL1_S_MCLK,
+                                       GLK_PLAT_CLK_FREQ, RT5682_PLL_FREQ);
+       if (ret < 0) {
+               dev_err(rtd->dev, "can't set codec pll: %d\n", ret);
+               return ret;
+       }
+
        /* Configure sysclk for codec */
        ret = snd_soc_dai_set_sysclk(codec_dai, RT5682_SCLK_S_PLL1,
                                        RT5682_PLL_FREQ, SND_SOC_CLOCK_IN);
index eab1f43..a402298 100644 (file)
@@ -146,7 +146,7 @@ static struct snd_soc_dai_link haswell_rt5640_dais[] = {
                .stream_name = "Loopback",
                .cpu_dai_name = "Loopback Pin",
                .platform_name = "haswell-pcm-audio",
-               .dynamic = 0,
+               .dynamic = 1,
                .codec_name = "snd-soc-dummy",
                .codec_dai_name = "snd-soc-dummy-dai",
                .trigger = {SND_SOC_DPCM_TRIGGER_POST, SND_SOC_DPCM_TRIGGER_POST},
index 60c9483..4ed5b7e 100644 (file)
@@ -336,9 +336,6 @@ static int skl_suspend(struct device *dev)
                skl->skl_sst->fw_loaded = false;
        }
 
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
-               snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
-
        return 0;
 }
 
@@ -350,10 +347,6 @@ static int skl_resume(struct device *dev)
        struct hdac_ext_link *hlink = NULL;
        int ret;
 
-       /* Turned OFF in HDMI codec driver after codec reconfiguration */
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
-               snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, true);
-
        /*
         * resume only when we are not in suspend active, otherwise need to
         * restore the device
@@ -446,8 +439,10 @@ static int skl_free(struct hdac_bus *bus)
        snd_hdac_ext_bus_exit(bus);
 
        cancel_work_sync(&skl->probe_work);
-       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI))
+       if (IS_ENABLED(CONFIG_SND_SOC_HDAC_HDMI)) {
+               snd_hdac_display_power(bus, HDA_CODEC_IDX_CONTROLLER, false);
                snd_hdac_i915_exit(bus);
+       }
 
        return 0;
 }
@@ -814,7 +809,7 @@ static void skl_probe_work(struct work_struct *work)
        err = skl_platform_register(bus->dev);
        if (err < 0) {
                dev_err(bus->dev, "platform register failed: %d\n", err);
-               return;
+               goto out_err;
        }
 
        err = skl_machine_device_register(skl);
index 5b986b7..548eb4f 100644 (file)
@@ -570,10 +570,10 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
        prtd->audio_client = q6asm_audio_client_alloc(dev,
                                        (q6asm_cb)compress_event_handler,
                                        prtd, stream_id, LEGACY_PCM_MODE);
-       if (!prtd->audio_client) {
+       if (IS_ERR(prtd->audio_client)) {
                dev_err(dev, "Could not allocate memory\n");
-               kfree(prtd);
-               return -ENOMEM;
+               ret = PTR_ERR(prtd->audio_client);
+               goto free_prtd;
        }
 
        size = COMPR_PLAYBACK_MAX_FRAGMENT_SIZE *
@@ -582,7 +582,7 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
                                  &prtd->dma_buffer);
        if (ret) {
                dev_err(dev, "Cannot allocate buffer(s)\n");
-               return ret;
+               goto free_client;
        }
 
        if (pdata->sid < 0)
@@ -595,6 +595,13 @@ static int q6asm_dai_compr_open(struct snd_compr_stream *stream)
        runtime->private_data = prtd;
 
        return 0;
+
+free_client:
+       q6asm_audio_client_free(prtd->audio_client);
+free_prtd:
+       kfree(prtd);
+
+       return ret;
 }
 
 static int q6asm_dai_compr_free(struct snd_compr_stream *stream)
@@ -874,7 +881,7 @@ static int of_q6asm_parse_dai_data(struct device *dev,
 
        for_each_child_of_node(dev->of_node, node) {
                ret = of_property_read_u32(node, "reg", &id);
-               if (ret || id > MAX_SESSIONS || id < 0) {
+               if (ret || id >= MAX_SESSIONS || id < 0) {
                        dev_err(dev, "valid dai id not found:%d\n", ret);
                        continue;
                }
index 1db8ef6..6f66a58 100644 (file)
@@ -158,17 +158,24 @@ static int sdm845_snd_hw_params(struct snd_pcm_substream *substream,
        return ret;
 }
 
+static void sdm845_jack_free(struct snd_jack *jack)
+{
+       struct snd_soc_component *component = jack->private_data;
+
+       snd_soc_component_set_jack(component, NULL, NULL);
+}
+
 static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd)
 {
        struct snd_soc_component *component;
-       struct snd_soc_dai_link *dai_link = rtd->dai_link;
        struct snd_soc_card *card = rtd->card;
+       struct snd_soc_dai *codec_dai = rtd->codec_dai;
+       struct snd_soc_dai *cpu_dai = rtd->cpu_dai;
        struct sdm845_snd_data *pdata = snd_soc_card_get_drvdata(card);
-       int i, rval;
+       struct snd_jack *jack;
+       int rval;
 
        if (!pdata->jack_setup) {
-               struct snd_jack *jack;
-
                rval = snd_soc_card_jack_new(card, "Headset Jack",
                                SND_JACK_HEADSET |
                                SND_JACK_HEADPHONE |
@@ -190,16 +197,22 @@ static int sdm845_dai_init(struct snd_soc_pcm_runtime *rtd)
                pdata->jack_setup = true;
        }
 
-       for (i = 0 ; i < dai_link->num_codecs; i++) {
-               struct snd_soc_dai *dai = rtd->codec_dais[i];
+       switch (cpu_dai->id) {
+       case PRIMARY_MI2S_RX:
+               jack  = pdata->jack.jack;
+               component = codec_dai->component;
 
-               component = dai->component;
-               rval = snd_soc_component_set_jack(
-                               component, &pdata->jack, NULL);
+               jack->private_data = component;
+               jack->private_free = sdm845_jack_free;
+               rval = snd_soc_component_set_jack(component,
+                                                 &pdata->jack, NULL);
                if (rval != 0 && rval != -ENOTSUPP) {
                        dev_warn(card->dev, "Failed to set jack: %d\n", rval);
                        return rval;
                }
+               break;
+       default:
+               break;
        }
 
        return 0;
index d6c62aa..d4bde48 100644 (file)
@@ -604,6 +604,7 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
        unsigned int fmt)
 {
        struct i2s_dai *i2s = to_info(dai);
+       struct i2s_dai *other = get_other_dai(i2s);
        int lrp_shift, sdf_shift, sdf_mask, lrp_rlow, mod_slave;
        u32 mod, tmp = 0;
        unsigned long flags;
@@ -661,7 +662,8 @@ static int i2s_set_fmt(struct snd_soc_dai *dai,
                 * CLK_I2S_RCLK_SRC clock is not exposed so we ensure any
                 * clock configuration assigned in DT is not overwritten.
                 */
-               if (i2s->rclk_srcrate == 0 && i2s->clk_data.clks == NULL)
+               if (i2s->rclk_srcrate == 0 && i2s->clk_data.clks == NULL &&
+                   other->clk_data.clks == NULL)
                        i2s_set_sysclk(dai, SAMSUNG_I2S_RCLKSRC_0,
                                                        0, SND_SOC_CLOCK_IN);
                break;
@@ -699,7 +701,9 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
        struct snd_pcm_hw_params *params, struct snd_soc_dai *dai)
 {
        struct i2s_dai *i2s = to_info(dai);
+       struct i2s_dai *other = get_other_dai(i2s);
        u32 mod, mask = 0, val = 0;
+       struct clk *rclksrc;
        unsigned long flags;
 
        WARN_ON(!pm_runtime_active(dai->dev));
@@ -782,6 +786,13 @@ static int i2s_hw_params(struct snd_pcm_substream *substream,
 
        i2s->frmclk = params_rate(params);
 
+       rclksrc = i2s->clk_table[CLK_I2S_RCLK_SRC];
+       if (!rclksrc || IS_ERR(rclksrc))
+               rclksrc = other->clk_table[CLK_I2S_RCLK_SRC];
+
+       if (rclksrc && !IS_ERR(rclksrc))
+               i2s->rclk_srcrate = clk_get_rate(rclksrc);
+
        return 0;
 }
 
@@ -886,11 +897,6 @@ static int config_setup(struct i2s_dai *i2s)
                return 0;
 
        if (!(i2s->quirks & QUIRK_NO_MUXPSR)) {
-               struct clk *rclksrc = i2s->clk_table[CLK_I2S_RCLK_SRC];
-
-               if (rclksrc && !IS_ERR(rclksrc))
-                       i2s->rclk_srcrate = clk_get_rate(rclksrc);
-
                psr = i2s->rclk_srcrate / i2s->frmclk / rfs;
                writel(((psr - 1) << 8) | PSR_PSREN, i2s->addr + I2SPSR);
                dev_dbg(&i2s->pdev->dev,
index 922fb6a..5aee11c 100644 (file)
@@ -202,7 +202,7 @@ static int camelot_prepare(struct snd_pcm_substream *substream)
        struct snd_soc_pcm_runtime *rtd = substream->private_data;
        struct camelot_pcm *cam = &cam_pcm_data[rtd->cpu_dai->id];
 
-       pr_debug("PCM data: addr 0x%08ulx len %d\n",
+       pr_debug("PCM data: addr 0x%08lx len %d\n",
                 (u32)runtime->dma_addr, runtime->dma_bytes);
  
        if (substream->stream == SNDRV_PCM_STREAM_PLAYBACK) {
index 59e250c..e819e96 100644 (file)
@@ -1526,14 +1526,14 @@ int rsnd_kctrl_new(struct rsnd_mod *mod,
        int ret;
 
        /*
-        * 1) Avoid duplicate register (ex. MIXer case)
-        * 2) re-register if card was rebinded
+        * 1) Avoid duplicate register for DVC with MIX case
+        * 2) Allow duplicate register for MIX
+        * 3) re-register if card was rebinded
         */
        list_for_each_entry(kctrl, &card->controls, list) {
                struct rsnd_kctrl_cfg *c = kctrl->private_data;
 
-               if (strcmp(kctrl->id.name, name) == 0 &&
-                   c->mod == mod)
+               if (c == cfg)
                        return 0;
        }
 
index 45ef295..f5afab6 100644 (file)
@@ -286,7 +286,7 @@ static int rsnd_ssi_master_clk_start(struct rsnd_mod *mod,
        if (rsnd_ssi_is_multi_slave(mod, io))
                return 0;
 
-       if (ssi->usrcnt > 1) {
+       if (ssi->usrcnt > 0) {
                if (ssi->rate != rate) {
                        dev_err(dev, "SSI parent/child should use same rate\n");
                        return -EINVAL;
index c5934ad..c74991d 100644 (file)
@@ -79,7 +79,7 @@ static int rsnd_ssiu_init(struct rsnd_mod *mod,
                break;
        case 9:
                for (i = 0; i < 4; i++)
-                       rsnd_mod_write(mod, SSI_SYS_STATUS((i * 2) + 1), 0xf << (id * 4));
+                       rsnd_mod_write(mod, SSI_SYS_STATUS((i * 2) + 1), 0xf << 4);
                break;
        }
 
index 0462b3e..50617db 100644 (file)
@@ -735,14 +735,19 @@ static struct snd_soc_component *soc_find_component(
        const struct device_node *of_node, const char *name)
 {
        struct snd_soc_component *component;
+       struct device_node *component_of_node;
 
        lockdep_assert_held(&client_mutex);
 
        for_each_component(component) {
                if (of_node) {
-                       if (component->dev->of_node == of_node)
+                       component_of_node = component->dev->of_node;
+                       if (!component_of_node && component->dev->parent)
+                               component_of_node = component->dev->parent->of_node;
+
+                       if (component_of_node == of_node)
                                return component;
-               } else if (strcmp(component->name, name) == 0) {
+               } else if (name && strcmp(component->name, name) == 0) {
                        return component;
                }
        }
@@ -951,7 +956,7 @@ static void soc_remove_dai(struct snd_soc_dai *dai, int order)
 {
        int err;
 
-       if (!dai || !dai->probed ||
+       if (!dai || !dai->probed || !dai->driver ||
            dai->driver->remove_order != order)
                return;
 
@@ -1034,17 +1039,18 @@ static int snd_soc_init_platform(struct snd_soc_card *card,
         * this function should be removed in the future
         */
        /* convert Legacy platform link */
-       if (!platform) {
+       if (!platform || dai_link->legacy_platform) {
                platform = devm_kzalloc(card->dev,
                                sizeof(struct snd_soc_dai_link_component),
                                GFP_KERNEL);
                if (!platform)
                        return -ENOMEM;
 
-               dai_link->platform      = platform;
-               platform->name          = dai_link->platform_name;
-               platform->of_node       = dai_link->platform_of_node;
-               platform->dai_name      = NULL;
+               dai_link->platform        = platform;
+               dai_link->legacy_platform = 1;
+               platform->name            = dai_link->platform_name;
+               platform->of_node         = dai_link->platform_of_node;
+               platform->dai_name        = NULL;
        }
 
        /* if there's no platform we match on the empty platform */
@@ -1129,6 +1135,15 @@ static int soc_init_dai_link(struct snd_soc_card *card,
                        link->name);
                return -EINVAL;
        }
+
+       /*
+        * Defer card registartion if platform dai component is not added to
+        * component list.
+        */
+       if ((link->platform->of_node || link->platform->name) &&
+           !soc_find_component(link->platform->of_node, link->platform->name))
+               return -EPROBE_DEFER;
+
        /*
         * CPU device may be specified by either name or OF node, but
         * can be left unspecified, and will be matched based on DAI
@@ -1140,6 +1155,15 @@ static int soc_init_dai_link(struct snd_soc_card *card,
                        link->name);
                return -EINVAL;
        }
+
+       /*
+        * Defer card registartion if cpu dai component is not added to
+        * component list.
+        */
+       if ((link->cpu_of_node || link->cpu_name) &&
+           !soc_find_component(link->cpu_of_node, link->cpu_name))
+               return -EPROBE_DEFER;
+
        /*
         * At least one of CPU DAI name or CPU device name/node must be
         * specified
@@ -2739,15 +2763,18 @@ int snd_soc_register_card(struct snd_soc_card *card)
        if (!card->name || !card->dev)
                return -EINVAL;
 
+       mutex_lock(&client_mutex);
        for_each_card_prelinks(card, i, link) {
 
                ret = soc_init_dai_link(card, link);
                if (ret) {
                        dev_err(card->dev, "ASoC: failed to init link %s\n",
                                link->name);
+                       mutex_unlock(&client_mutex);
                        return ret;
                }
        }
+       mutex_unlock(&client_mutex);
 
        dev_set_drvdata(card->dev, card);
 
index a517884..20bad75 100644 (file)
@@ -70,12 +70,16 @@ static int dapm_up_seq[] = {
        [snd_soc_dapm_clock_supply] = 1,
        [snd_soc_dapm_supply] = 2,
        [snd_soc_dapm_micbias] = 3,
+       [snd_soc_dapm_vmid] = 3,
        [snd_soc_dapm_dai_link] = 2,
        [snd_soc_dapm_dai_in] = 4,
        [snd_soc_dapm_dai_out] = 4,
        [snd_soc_dapm_aif_in] = 4,
        [snd_soc_dapm_aif_out] = 4,
        [snd_soc_dapm_mic] = 5,
+       [snd_soc_dapm_siggen] = 5,
+       [snd_soc_dapm_input] = 5,
+       [snd_soc_dapm_output] = 5,
        [snd_soc_dapm_mux] = 6,
        [snd_soc_dapm_demux] = 6,
        [snd_soc_dapm_dac] = 7,
@@ -83,11 +87,19 @@ static int dapm_up_seq[] = {
        [snd_soc_dapm_mixer] = 8,
        [snd_soc_dapm_mixer_named_ctl] = 8,
        [snd_soc_dapm_pga] = 9,
+       [snd_soc_dapm_buffer] = 9,
+       [snd_soc_dapm_scheduler] = 9,
+       [snd_soc_dapm_effect] = 9,
+       [snd_soc_dapm_src] = 9,
+       [snd_soc_dapm_asrc] = 9,
+       [snd_soc_dapm_encoder] = 9,
+       [snd_soc_dapm_decoder] = 9,
        [snd_soc_dapm_adc] = 10,
        [snd_soc_dapm_out_drv] = 11,
        [snd_soc_dapm_hp] = 11,
        [snd_soc_dapm_spk] = 11,
        [snd_soc_dapm_line] = 11,
+       [snd_soc_dapm_sink] = 11,
        [snd_soc_dapm_kcontrol] = 12,
        [snd_soc_dapm_post] = 13,
 };
@@ -100,13 +112,25 @@ static int dapm_down_seq[] = {
        [snd_soc_dapm_spk] = 3,
        [snd_soc_dapm_line] = 3,
        [snd_soc_dapm_out_drv] = 3,
+       [snd_soc_dapm_sink] = 3,
        [snd_soc_dapm_pga] = 4,
+       [snd_soc_dapm_buffer] = 4,
+       [snd_soc_dapm_scheduler] = 4,
+       [snd_soc_dapm_effect] = 4,
+       [snd_soc_dapm_src] = 4,
+       [snd_soc_dapm_asrc] = 4,
+       [snd_soc_dapm_encoder] = 4,
+       [snd_soc_dapm_decoder] = 4,
        [snd_soc_dapm_switch] = 5,
        [snd_soc_dapm_mixer_named_ctl] = 5,
        [snd_soc_dapm_mixer] = 5,
        [snd_soc_dapm_dac] = 6,
        [snd_soc_dapm_mic] = 7,
+       [snd_soc_dapm_siggen] = 7,
+       [snd_soc_dapm_input] = 7,
+       [snd_soc_dapm_output] = 7,
        [snd_soc_dapm_micbias] = 8,
+       [snd_soc_dapm_vmid] = 8,
        [snd_soc_dapm_mux] = 9,
        [snd_soc_dapm_demux] = 9,
        [snd_soc_dapm_aif_in] = 10,
@@ -2019,19 +2043,19 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
                out = is_connected_output_ep(w, NULL, NULL);
        }
 
-       ret = snprintf(buf, PAGE_SIZE, "%s: %s%s  in %d out %d",
+       ret = scnprintf(buf, PAGE_SIZE, "%s: %s%s  in %d out %d",
                       w->name, w->power ? "On" : "Off",
                       w->force ? " (forced)" : "", in, out);
 
        if (w->reg >= 0)
-               ret += snprintf(buf + ret, PAGE_SIZE - ret,
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                " - R%d(0x%x) mask 0x%x",
                                w->reg, w->reg, w->mask << w->shift);
 
-       ret += snprintf(buf + ret, PAGE_SIZE - ret, "\n");
+       ret += scnprintf(buf + ret, PAGE_SIZE - ret, "\n");
 
        if (w->sname)
-               ret += snprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
+               ret += scnprintf(buf + ret, PAGE_SIZE - ret, " stream %s %s\n",
                                w->sname,
                                w->active ? "active" : "inactive");
 
@@ -2044,7 +2068,7 @@ static ssize_t dapm_widget_power_read_file(struct file *file,
                        if (!p->connect)
                                continue;
 
-                       ret += snprintf(buf + ret, PAGE_SIZE - ret,
+                       ret += scnprintf(buf + ret, PAGE_SIZE - ret,
                                        " %s  \"%s\" \"%s\"\n",
                                        (rdir == SND_SOC_DAPM_DIR_IN) ? "in" : "out",
                                        p->name ? p->name : "static",
index 045ef13..731b963 100644 (file)
@@ -502,6 +502,7 @@ static void remove_dai(struct snd_soc_component *comp,
 {
        struct snd_soc_dai_driver *dai_drv =
                container_of(dobj, struct snd_soc_dai_driver, dobj);
+       struct snd_soc_dai *dai;
 
        if (pass != SOC_TPLG_PASS_PCM_DAI)
                return;
@@ -509,6 +510,10 @@ static void remove_dai(struct snd_soc_component *comp,
        if (dobj->ops && dobj->ops->dai_unload)
                dobj->ops->dai_unload(comp, dobj);
 
+       list_for_each_entry(dai, &comp->dai_list, list)
+               if (dai->driver == dai_drv)
+                       dai->driver = NULL;
+
        kfree(dai_drv->name);
        list_del(&dobj->list);
        kfree(dai_drv);
@@ -2482,6 +2487,7 @@ int snd_soc_tplg_component_load(struct snd_soc_component *comp,
        struct snd_soc_tplg_ops *ops, const struct firmware *fw, u32 id)
 {
        struct soc_tplg tplg;
+       int ret;
 
        /* setup parsing context */
        memset(&tplg, 0, sizeof(tplg));
@@ -2495,7 +2501,12 @@ int snd_soc_tplg_component_load(struct snd_soc_component *comp,
        tplg.bytes_ext_ops = ops->bytes_ext_ops;
        tplg.bytes_ext_ops_count = ops->bytes_ext_ops_count;
 
-       return soc_tplg_load(&tplg);
+       ret = soc_tplg_load(&tplg);
+       /* free the created components if fail to load topology */
+       if (ret)
+               snd_soc_tplg_component_remove(comp, SND_SOC_TPLG_INDEX_ALL);
+
+       return ret;
 }
 EXPORT_SYMBOL_GPL(snd_soc_tplg_component_load);
 
index eeda6d5..a10fcb5 100644 (file)
@@ -108,7 +108,7 @@ struct davinci_mcasp {
        /* Used for comstraint setting on the second stream */
        u32     channels;
 
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
        struct davinci_mcasp_context context;
 #endif
 
@@ -1486,74 +1486,6 @@ static int davinci_mcasp_dai_probe(struct snd_soc_dai *dai)
        return 0;
 }
 
-#ifdef CONFIG_PM_SLEEP
-static int davinci_mcasp_suspend(struct snd_soc_dai *dai)
-{
-       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
-       struct davinci_mcasp_context *context = &mcasp->context;
-       u32 reg;
-       int i;
-
-       context->pm_state = pm_runtime_active(mcasp->dev);
-       if (!context->pm_state)
-               pm_runtime_get_sync(mcasp->dev);
-
-       for (i = 0; i < ARRAY_SIZE(context_regs); i++)
-               context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]);
-
-       if (mcasp->txnumevt) {
-               reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
-               context->afifo_regs[0] = mcasp_get_reg(mcasp, reg);
-       }
-       if (mcasp->rxnumevt) {
-               reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
-               context->afifo_regs[1] = mcasp_get_reg(mcasp, reg);
-       }
-
-       for (i = 0; i < mcasp->num_serializer; i++)
-               context->xrsr_regs[i] = mcasp_get_reg(mcasp,
-                                               DAVINCI_MCASP_XRSRCTL_REG(i));
-
-       pm_runtime_put_sync(mcasp->dev);
-
-       return 0;
-}
-
-static int davinci_mcasp_resume(struct snd_soc_dai *dai)
-{
-       struct davinci_mcasp *mcasp = snd_soc_dai_get_drvdata(dai);
-       struct davinci_mcasp_context *context = &mcasp->context;
-       u32 reg;
-       int i;
-
-       pm_runtime_get_sync(mcasp->dev);
-
-       for (i = 0; i < ARRAY_SIZE(context_regs); i++)
-               mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]);
-
-       if (mcasp->txnumevt) {
-               reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
-               mcasp_set_reg(mcasp, reg, context->afifo_regs[0]);
-       }
-       if (mcasp->rxnumevt) {
-               reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
-               mcasp_set_reg(mcasp, reg, context->afifo_regs[1]);
-       }
-
-       for (i = 0; i < mcasp->num_serializer; i++)
-               mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
-                             context->xrsr_regs[i]);
-
-       if (!context->pm_state)
-               pm_runtime_put_sync(mcasp->dev);
-
-       return 0;
-}
-#else
-#define davinci_mcasp_suspend NULL
-#define davinci_mcasp_resume NULL
-#endif
-
 #define DAVINCI_MCASP_RATES    SNDRV_PCM_RATE_8000_192000
 
 #define DAVINCI_MCASP_PCM_FMTS (SNDRV_PCM_FMTBIT_S8 | \
@@ -1571,8 +1503,6 @@ static struct snd_soc_dai_driver davinci_mcasp_dai[] = {
        {
                .name           = "davinci-mcasp.0",
                .probe          = davinci_mcasp_dai_probe,
-               .suspend        = davinci_mcasp_suspend,
-               .resume         = davinci_mcasp_resume,
                .playback       = {
                        .channels_min   = 1,
                        .channels_max   = 32 * 16,
@@ -1976,7 +1906,7 @@ static int davinci_mcasp_probe(struct platform_device *pdev)
        }
 
        mcasp->num_serializer = pdata->num_serializer;
-#ifdef CONFIG_PM_SLEEP
+#ifdef CONFIG_PM
        mcasp->context.xrsr_regs = devm_kcalloc(&pdev->dev,
                                        mcasp->num_serializer, sizeof(u32),
                                        GFP_KERNEL);
@@ -2196,11 +2126,73 @@ static int davinci_mcasp_remove(struct platform_device *pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int davinci_mcasp_runtime_suspend(struct device *dev)
+{
+       struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
+       struct davinci_mcasp_context *context = &mcasp->context;
+       u32 reg;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(context_regs); i++)
+               context->config_regs[i] = mcasp_get_reg(mcasp, context_regs[i]);
+
+       if (mcasp->txnumevt) {
+               reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
+               context->afifo_regs[0] = mcasp_get_reg(mcasp, reg);
+       }
+       if (mcasp->rxnumevt) {
+               reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
+               context->afifo_regs[1] = mcasp_get_reg(mcasp, reg);
+       }
+
+       for (i = 0; i < mcasp->num_serializer; i++)
+               context->xrsr_regs[i] = mcasp_get_reg(mcasp,
+                                               DAVINCI_MCASP_XRSRCTL_REG(i));
+
+       return 0;
+}
+
+static int davinci_mcasp_runtime_resume(struct device *dev)
+{
+       struct davinci_mcasp *mcasp = dev_get_drvdata(dev);
+       struct davinci_mcasp_context *context = &mcasp->context;
+       u32 reg;
+       int i;
+
+       for (i = 0; i < ARRAY_SIZE(context_regs); i++)
+               mcasp_set_reg(mcasp, context_regs[i], context->config_regs[i]);
+
+       if (mcasp->txnumevt) {
+               reg = mcasp->fifo_base + MCASP_WFIFOCTL_OFFSET;
+               mcasp_set_reg(mcasp, reg, context->afifo_regs[0]);
+       }
+       if (mcasp->rxnumevt) {
+               reg = mcasp->fifo_base + MCASP_RFIFOCTL_OFFSET;
+               mcasp_set_reg(mcasp, reg, context->afifo_regs[1]);
+       }
+
+       for (i = 0; i < mcasp->num_serializer; i++)
+               mcasp_set_reg(mcasp, DAVINCI_MCASP_XRSRCTL_REG(i),
+                             context->xrsr_regs[i]);
+
+       return 0;
+}
+
+#endif
+
+static const struct dev_pm_ops davinci_mcasp_pm_ops = {
+       SET_RUNTIME_PM_OPS(davinci_mcasp_runtime_suspend,
+                          davinci_mcasp_runtime_resume,
+                          NULL)
+};
+
 static struct platform_driver davinci_mcasp_driver = {
        .probe          = davinci_mcasp_probe,
        .remove         = davinci_mcasp_remove,
        .driver         = {
                .name   = "davinci-mcasp",
+               .pm     = &davinci_mcasp_pm_ops,
                .of_match_table = mcasp_dt_ids,
        },
 };
index 25e287f..723a583 100644 (file)
@@ -1,5 +1,5 @@
 config SND_SOC_XILINX_I2S
-       tristate "Audio support for the the Xilinx I2S"
+       tristate "Audio support for the Xilinx I2S"
        help
          Select this option to enable Xilinx I2S Audio. This enables
          I2S playback and capture using xilinx soft IP. In transmitter
index d4ae9ef..8b35316 100644 (file)
@@ -1,12 +1,11 @@
 // SPDX-License-Identifier: GPL-2.0
-/*
- * Xilinx ASoC I2S audio support
- *
- * Copyright (C) 2018 Xilinx, Inc.
- *
- * Author: Praveen Vuppala <praveenv@xilinx.com>
- * Author: Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>
- */
+//
+// Xilinx ASoC I2S audio support
+//
+// Copyright (C) 2018 Xilinx, Inc.
+//
+// Author: Praveen Vuppala <praveenv@xilinx.com>
+// Author: Maruthi Srinivas Bayyavarapu <maruthis@xilinx.com>
 
 #include <linux/io.h>
 #include <linux/module.h>
index 7609ece..9e71d7c 100644 (file)
@@ -2541,8 +2541,8 @@ static int snd_dbri_create(struct snd_card *card,
        dbri->op = op;
        dbri->irq = irq;
 
-       dbri->dma = dma_zalloc_coherent(&op->dev, sizeof(struct dbri_dma),
-                                       &dbri->dma_dvma, GFP_KERNEL);
+       dbri->dma = dma_alloc_coherent(&op->dev, sizeof(struct dbri_dma),
+                                      &dbri->dma_dvma, GFP_KERNEL);
        if (!dbri->dma)
                return -ENOMEM;
 
index a105947..746a72e 100644 (file)
@@ -246,7 +246,7 @@ static int snd_usb_create_streams(struct snd_usb_audio *chip, int ctrlif)
                h1 = snd_usb_find_csint_desc(host_iface->extra,
                                                         host_iface->extralen,
                                                         NULL, UAC_HEADER);
-               if (!h1) {
+               if (!h1 || h1->bLength < sizeof(*h1)) {
                        dev_err(&dev->dev, "cannot find UAC_HEADER\n");
                        return -EINVAL;
                }
index c63c84b..e7d441d 100644 (file)
@@ -753,8 +753,9 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
                                       struct uac_mixer_unit_descriptor *desc)
 {
        int mu_channels;
+       void *c;
 
-       if (desc->bLength < 11)
+       if (desc->bLength < sizeof(*desc))
                return -EINVAL;
        if (!desc->bNrInPins)
                return -EINVAL;
@@ -763,6 +764,8 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
        case UAC_VERSION_1:
        case UAC_VERSION_2:
        default:
+               if (desc->bLength < sizeof(*desc) + desc->bNrInPins + 1)
+                       return 0; /* no bmControls -> skip */
                mu_channels = uac_mixer_unit_bNrChannels(desc);
                break;
        case UAC_VERSION_3:
@@ -772,7 +775,11 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
        }
 
        if (!mu_channels)
-               return -EINVAL;
+               return 0;
+
+       c = uac_mixer_unit_bmControls(desc, state->mixer->protocol);
+       if (c - (void *)desc + (mu_channels - 1) / 8 >= desc->bLength)
+               return 0; /* no bmControls -> skip */
 
        return mu_channels;
 }
@@ -944,7 +951,7 @@ static int check_input_term(struct mixer_build *state, int id,
                                struct uac_mixer_unit_descriptor *d = p1;
 
                                err = uac_mixer_unit_get_channels(state, d);
-                               if (err < 0)
+                               if (err <= 0)
                                        return err;
 
                                term->channels = err;
@@ -2068,11 +2075,15 @@ static int parse_audio_input_terminal(struct mixer_build *state, int unitid,
 
        if (state->mixer->protocol == UAC_VERSION_2) {
                struct uac2_input_terminal_descriptor *d_v2 = raw_desc;
+               if (d_v2->bLength < sizeof(*d_v2))
+                       return -EINVAL;
                control = UAC2_TE_CONNECTOR;
                term_id = d_v2->bTerminalID;
                bmctls = le16_to_cpu(d_v2->bmControls);
        } else if (state->mixer->protocol == UAC_VERSION_3) {
                struct uac3_input_terminal_descriptor *d_v3 = raw_desc;
+               if (d_v3->bLength < sizeof(*d_v3))
+                       return -EINVAL;
                control = UAC3_TE_INSERTION;
                term_id = d_v3->bTerminalID;
                bmctls = le32_to_cpu(d_v3->bmControls);
@@ -2118,7 +2129,7 @@ static int parse_audio_mixer_unit(struct mixer_build *state, int unitid,
                if (err < 0)
                        continue;
                /* no bmControls field (e.g. Maya44) -> ignore */
-               if (desc->bLength <= 10 + input_pins)
+               if (!num_outs)
                        continue;
                err = check_input_term(state, desc->baSourceID[pin], &iterm);
                if (err < 0)
@@ -2314,7 +2325,7 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
                                char *name)
 {
        struct uac_processing_unit_descriptor *desc = raw_desc;
-       int num_ins = desc->bNrInPins;
+       int num_ins;
        struct usb_mixer_elem_info *cval;
        struct snd_kcontrol *kctl;
        int i, err, nameid, type, len;
@@ -2329,7 +2340,13 @@ static int build_audio_procunit(struct mixer_build *state, int unitid,
                0, NULL, default_value_info
        };
 
-       if (desc->bLength < 13 || desc->bLength < 13 + num_ins ||
+       if (desc->bLength < 13) {
+               usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid);
+               return -EINVAL;
+       }
+
+       num_ins = desc->bNrInPins;
+       if (desc->bLength < 13 + num_ins ||
            desc->bLength < num_ins + uac_processing_unit_bControlSize(desc, state->mixer->protocol)) {
                usb_audio_err(state->chip, "invalid %s descriptor (id %d)\n", name, unitid);
                return -EINVAL;
index 3828471..db114f3 100644 (file)
@@ -314,6 +314,9 @@ static int search_roland_implicit_fb(struct usb_device *dev, int ifnum,
        return 0;
 }
 
+/* Setup an implicit feedback endpoint from a quirk. Returns 0 if no quirk
+ * applies. Returns 1 if a quirk was found.
+ */
 static int set_sync_ep_implicit_fb_quirk(struct snd_usb_substream *subs,
                                         struct usb_device *dev,
                                         struct usb_interface_descriptor *altsd,
@@ -384,7 +387,7 @@ add_sync_ep:
 
        subs->data_endpoint->sync_master = subs->sync_endpoint;
 
-       return 0;
+       return 1;
 }
 
 static int set_sync_endpoint(struct snd_usb_substream *subs,
@@ -423,6 +426,10 @@ static int set_sync_endpoint(struct snd_usb_substream *subs,
        if (err < 0)
                return err;
 
+       /* endpoint set by quirk */
+       if (err > 0)
+               return 0;
+
        if (altsd->bNumEndpoints < 2)
                return 0;
 
index 37fc044..b345beb 100644 (file)
@@ -3326,6 +3326,9 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                                        }
                                }
                        },
+                       {
+                               .ifnum = -1
+                       },
                }
        }
 },
@@ -3369,6 +3372,9 @@ AU0828_DEVICE(0x2040, 0x7270, "Hauppauge", "HVR-950Q"),
                                        }
                                }
                        },
+                       {
+                               .ifnum = -1
+                       },
                }
        }
 },
index 96340f2..7e65fe8 100644 (file)
@@ -768,7 +768,7 @@ static int snd_usb_cm6206_boot_quirk(struct usb_device *dev)
                 * REG1: PLL binary search enable, soft mute enable.
                 */
                CM6206_REG1_PLLBIN_EN |
-               CM6206_REG1_SOFT_MUTE_EN |
+               CM6206_REG1_SOFT_MUTE_EN,
                /*
                 * REG2: enable output drivers,
                 * select front channels to the headphone output,
@@ -1492,6 +1492,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
                        return SNDRV_PCM_FMTBIT_DSD_U32_BE;
                break;
 
+       case USB_ID(0x10cb, 0x0103): /* The Bit Opus #3; with fp->dsd_raw */
        case USB_ID(0x152a, 0x85de): /* SMSL D1 DAC */
        case USB_ID(0x16d0, 0x09dd): /* Encore mDSD */
        case USB_ID(0x0d8c, 0x0316): /* Hegel HD12 DSD */
@@ -1566,6 +1567,7 @@ u64 snd_usb_interface_dsd_format_quirks(struct snd_usb_audio *chip,
        case 0x20b1:  /* XMOS based devices */
        case 0x152a:  /* Thesycon devices */
        case 0x25ce:  /* Mytek devices */
+       case 0x2ab6:  /* T+A devices */
                if (fp->dsd_raw)
                        return SNDRV_PCM_FMTBIT_DSD_U32_BE;
                break;
index 67cf849..d9e3de4 100644 (file)
@@ -596,12 +596,8 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
                csep = snd_usb_find_desc(alts->extra, alts->extralen, NULL, USB_DT_CS_ENDPOINT);
 
        if (!csep || csep->bLength < 7 ||
-           csep->bDescriptorSubtype != UAC_EP_GENERAL) {
-               usb_audio_warn(chip,
-                              "%u:%d : no or invalid class specific endpoint descriptor\n",
-                              iface_no, altsd->bAlternateSetting);
-               return 0;
-       }
+           csep->bDescriptorSubtype != UAC_EP_GENERAL)
+               goto error;
 
        if (protocol == UAC_VERSION_1) {
                attributes = csep->bmAttributes;
@@ -609,6 +605,8 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
                struct uac2_iso_endpoint_descriptor *csep2 =
                        (struct uac2_iso_endpoint_descriptor *) csep;
 
+               if (csep2->bLength < sizeof(*csep2))
+                       goto error;
                attributes = csep->bmAttributes & UAC_EP_CS_ATTR_FILL_MAX;
 
                /* emulate the endpoint attributes of a v1 device */
@@ -618,12 +616,20 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
                struct uac3_iso_endpoint_descriptor *csep3 =
                        (struct uac3_iso_endpoint_descriptor *) csep;
 
+               if (csep3->bLength < sizeof(*csep3))
+                       goto error;
                /* emulate the endpoint attributes of a v1 device */
                if (le32_to_cpu(csep3->bmControls) & UAC2_CONTROL_PITCH)
                        attributes |= UAC_EP_CS_ATTR_PITCH_CONTROL;
        }
 
        return attributes;
+
+ error:
+       usb_audio_warn(chip,
+                      "%u:%d : no or invalid class specific endpoint descriptor\n",
+                      iface_no, altsd->bAlternateSetting);
+       return 0;
 }
 
 /* find an input terminal descriptor (either UAC1 or UAC2) with the given
@@ -631,13 +637,17 @@ static int parse_uac_endpoint_attributes(struct snd_usb_audio *chip,
  */
 static void *
 snd_usb_find_input_terminal_descriptor(struct usb_host_interface *ctrl_iface,
-                                              int terminal_id)
+                                      int terminal_id, bool uac23)
 {
        struct uac2_input_terminal_descriptor *term = NULL;
+       size_t minlen = uac23 ? sizeof(struct uac2_input_terminal_descriptor) :
+               sizeof(struct uac_input_terminal_descriptor);
 
        while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
                                               ctrl_iface->extralen,
                                               term, UAC_INPUT_TERMINAL))) {
+               if (term->bLength < minlen)
+                       continue;
                if (term->bTerminalID == terminal_id)
                        return term;
        }
@@ -655,7 +665,8 @@ snd_usb_find_output_terminal_descriptor(struct usb_host_interface *ctrl_iface,
        while ((term = snd_usb_find_csint_desc(ctrl_iface->extra,
                                               ctrl_iface->extralen,
                                               term, UAC_OUTPUT_TERMINAL))) {
-               if (term->bTerminalID == terminal_id)
+               if (term->bLength >= sizeof(*term) &&
+                   term->bTerminalID == terminal_id)
                        return term;
        }
 
@@ -729,7 +740,8 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
                format = le16_to_cpu(as->wFormatTag); /* remember the format value */
 
                iterm = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-                                                            as->bTerminalLink);
+                                                              as->bTerminalLink,
+                                                              false);
                if (iterm) {
                        num_channels = iterm->bNrChannels;
                        chconfig = le16_to_cpu(iterm->wChannelConfig);
@@ -764,7 +776,8 @@ snd_usb_get_audioformat_uac12(struct snd_usb_audio *chip,
                 * to extract the clock
                 */
                input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-                                                                   as->bTerminalLink);
+                                                                   as->bTerminalLink,
+                                                                   true);
                if (input_term) {
                        clock = input_term->bCSourceID;
                        if (!chconfig && (num_channels == input_term->bNrChannels))
@@ -998,7 +1011,8 @@ snd_usb_get_audioformat_uac3(struct snd_usb_audio *chip,
         * to extract the clock
         */
        input_term = snd_usb_find_input_terminal_descriptor(chip->ctrl_intf,
-                                                           as->bTerminalLink);
+                                                           as->bTerminalLink,
+                                                           true);
        if (input_term) {
                clock = input_term->bCSourceID;
                goto found_clock;
index ff91192..f599064 100644 (file)
@@ -47,6 +47,7 @@ enum perf_event_powerpc_regs {
        PERF_REG_POWERPC_DAR,
        PERF_REG_POWERPC_DSISR,
        PERF_REG_POWERPC_SIER,
+       PERF_REG_POWERPC_MMCRA,
        PERF_REG_POWERPC_MAX,
 };
 #endif /* _UAPI_ASM_POWERPC_PERF_REGS_H */
diff --git a/tools/arch/powerpc/include/uapi/asm/unistd.h b/tools/arch/powerpc/include/uapi/asm/unistd.h
deleted file mode 100644 (file)
index 985534d..0000000
+++ /dev/null
@@ -1,404 +0,0 @@
-/* SPDX-License-Identifier: GPL-2.0+ WITH Linux-syscall-note */
-/*
- * This file contains the system call numbers.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- */
-#ifndef _UAPI_ASM_POWERPC_UNISTD_H_
-#define _UAPI_ASM_POWERPC_UNISTD_H_
-
-
-#define __NR_restart_syscall     0
-#define __NR_exit                1
-#define __NR_fork                2
-#define __NR_read                3
-#define __NR_write               4
-#define __NR_open                5
-#define __NR_close               6
-#define __NR_waitpid             7
-#define __NR_creat               8
-#define __NR_link                9
-#define __NR_unlink             10
-#define __NR_execve             11
-#define __NR_chdir              12
-#define __NR_time               13
-#define __NR_mknod              14
-#define __NR_chmod              15
-#define __NR_lchown             16
-#define __NR_break              17
-#define __NR_oldstat            18
-#define __NR_lseek              19
-#define __NR_getpid             20
-#define __NR_mount              21
-#define __NR_umount             22
-#define __NR_setuid             23
-#define __NR_getuid             24
-#define __NR_stime              25
-#define __NR_ptrace             26
-#define __NR_alarm              27
-#define __NR_oldfstat           28
-#define __NR_pause              29
-#define __NR_utime              30
-#define __NR_stty               31
-#define __NR_gtty               32
-#define __NR_access             33
-#define __NR_nice               34
-#define __NR_ftime              35
-#define __NR_sync               36
-#define __NR_kill               37
-#define __NR_rename             38
-#define __NR_mkdir              39
-#define __NR_rmdir              40
-#define __NR_dup                41
-#define __NR_pipe               42
-#define __NR_times              43
-#define __NR_prof               44
-#define __NR_brk                45
-#define __NR_setgid             46
-#define __NR_getgid             47
-#define __NR_signal             48
-#define __NR_geteuid            49
-#define __NR_getegid            50
-#define __NR_acct               51
-#define __NR_umount2            52
-#define __NR_lock               53
-#define __NR_ioctl              54
-#define __NR_fcntl              55
-#define __NR_mpx                56
-#define __NR_setpgid            57
-#define __NR_ulimit             58
-#define __NR_oldolduname        59
-#define __NR_umask              60
-#define __NR_chroot             61
-#define __NR_ustat              62
-#define __NR_dup2               63
-#define __NR_getppid            64
-#define __NR_getpgrp            65
-#define __NR_setsid             66
-#define __NR_sigaction          67
-#define __NR_sgetmask           68
-#define __NR_ssetmask           69
-#define __NR_setreuid           70
-#define __NR_setregid           71
-#define __NR_sigsuspend                 72
-#define __NR_sigpending                 73
-#define __NR_sethostname        74
-#define __NR_setrlimit          75
-#define __NR_getrlimit          76
-#define __NR_getrusage          77
-#define __NR_gettimeofday       78
-#define __NR_settimeofday       79
-#define __NR_getgroups          80
-#define __NR_setgroups          81
-#define __NR_select             82
-#define __NR_symlink            83
-#define __NR_oldlstat           84
-#define __NR_readlink           85
-#define __NR_uselib             86
-#define __NR_swapon             87
-#define __NR_reboot             88
-#define __NR_readdir            89
-#define __NR_mmap               90
-#define __NR_munmap             91
-#define __NR_truncate           92
-#define __NR_ftruncate          93
-#define __NR_fchmod             94
-#define __NR_fchown             95
-#define __NR_getpriority        96
-#define __NR_setpriority        97
-#define __NR_profil             98
-#define __NR_statfs             99
-#define __NR_fstatfs           100
-#define __NR_ioperm            101
-#define __NR_socketcall                102
-#define __NR_syslog            103
-#define __NR_setitimer         104
-#define __NR_getitimer         105
-#define __NR_stat              106
-#define __NR_lstat             107
-#define __NR_fstat             108
-#define __NR_olduname          109
-#define __NR_iopl              110
-#define __NR_vhangup           111
-#define __NR_idle              112
-#define __NR_vm86              113
-#define __NR_wait4             114
-#define __NR_swapoff           115
-#define __NR_sysinfo           116
-#define __NR_ipc               117
-#define __NR_fsync             118
-#define __NR_sigreturn         119
-#define __NR_clone             120
-#define __NR_setdomainname     121
-#define __NR_uname             122
-#define __NR_modify_ldt                123
-#define __NR_adjtimex          124
-#define __NR_mprotect          125
-#define __NR_sigprocmask       126
-#define __NR_create_module     127
-#define __NR_init_module       128
-#define __NR_delete_module     129
-#define __NR_get_kernel_syms   130
-#define __NR_quotactl          131
-#define __NR_getpgid           132
-#define __NR_fchdir            133
-#define __NR_bdflush           134
-#define __NR_sysfs             135
-#define __NR_personality       136
-#define __NR_afs_syscall       137 /* Syscall for Andrew File System */
-#define __NR_setfsuid          138
-#define __NR_setfsgid          139
-#define __NR__llseek           140
-#define __NR_getdents          141
-#define __NR__newselect                142
-#define __NR_flock             143
-#define __NR_msync             144
-#define __NR_readv             145
-#define __NR_writev            146
-#define __NR_getsid            147
-#define __NR_fdatasync         148
-#define __NR__sysctl           149
-#define __NR_mlock             150
-#define __NR_munlock           151
-#define __NR_mlockall          152
-#define __NR_munlockall                153
-#define __NR_sched_setparam            154
-#define __NR_sched_getparam            155
-#define __NR_sched_setscheduler                156
-#define __NR_sched_getscheduler                157
-#define __NR_sched_yield               158
-#define __NR_sched_get_priority_max    159
-#define __NR_sched_get_priority_min    160
-#define __NR_sched_rr_get_interval     161
-#define __NR_nanosleep         162
-#define __NR_mremap            163
-#define __NR_setresuid         164
-#define __NR_getresuid         165
-#define __NR_query_module      166
-#define __NR_poll              167
-#define __NR_nfsservctl                168
-#define __NR_setresgid         169
-#define __NR_getresgid         170
-#define __NR_prctl             171
-#define __NR_rt_sigreturn      172
-#define __NR_rt_sigaction      173
-#define __NR_rt_sigprocmask    174
-#define __NR_rt_sigpending     175
-#define __NR_rt_sigtimedwait   176
-#define __NR_rt_sigqueueinfo   177
-#define __NR_rt_sigsuspend     178
-#define __NR_pread64           179
-#define __NR_pwrite64          180
-#define __NR_chown             181
-#define __NR_getcwd            182
-#define __NR_capget            183
-#define __NR_capset            184
-#define __NR_sigaltstack       185
-#define __NR_sendfile          186
-#define __NR_getpmsg           187     /* some people actually want streams */
-#define __NR_putpmsg           188     /* some people actually want streams */
-#define __NR_vfork             189
-#define __NR_ugetrlimit                190     /* SuS compliant getrlimit */
-#define __NR_readahead         191
-#ifndef __powerpc64__                  /* these are 32-bit only */
-#define __NR_mmap2             192
-#define __NR_truncate64                193
-#define __NR_ftruncate64       194
-#define __NR_stat64            195
-#define __NR_lstat64           196
-#define __NR_fstat64           197
-#endif
-#define __NR_pciconfig_read    198
-#define __NR_pciconfig_write   199
-#define __NR_pciconfig_iobase  200
-#define __NR_multiplexer       201
-#define __NR_getdents64                202
-#define __NR_pivot_root                203
-#ifndef __powerpc64__
-#define __NR_fcntl64           204
-#endif
-#define __NR_madvise           205
-#define __NR_mincore           206
-#define __NR_gettid            207
-#define __NR_tkill             208
-#define __NR_setxattr          209
-#define __NR_lsetxattr         210
-#define __NR_fsetxattr         211
-#define __NR_getxattr          212
-#define __NR_lgetxattr         213
-#define __NR_fgetxattr         214
-#define __NR_listxattr         215
-#define __NR_llistxattr                216
-#define __NR_flistxattr                217
-#define __NR_removexattr       218
-#define __NR_lremovexattr      219
-#define __NR_fremovexattr      220
-#define __NR_futex             221
-#define __NR_sched_setaffinity 222
-#define __NR_sched_getaffinity 223
-/* 224 currently unused */
-#define __NR_tuxcall           225
-#ifndef __powerpc64__
-#define __NR_sendfile64                226
-#endif
-#define __NR_io_setup          227
-#define __NR_io_destroy                228
-#define __NR_io_getevents      229
-#define __NR_io_submit         230
-#define __NR_io_cancel         231
-#define __NR_set_tid_address   232
-#define __NR_fadvise64         233
-#define __NR_exit_group                234
-#define __NR_lookup_dcookie    235
-#define __NR_epoll_create      236
-#define __NR_epoll_ctl         237
-#define __NR_epoll_wait                238
-#define __NR_remap_file_pages  239
-#define __NR_timer_create      240
-#define __NR_timer_settime     241
-#define __NR_timer_gettime     242
-#define __NR_timer_getoverrun  243
-#define __NR_timer_delete      244
-#define __NR_clock_settime     245
-#define __NR_clock_gettime     246
-#define __NR_clock_getres      247
-#define __NR_clock_nanosleep   248
-#define __NR_swapcontext       249
-#define __NR_tgkill            250
-#define __NR_utimes            251
-#define __NR_statfs64          252
-#define __NR_fstatfs64         253
-#ifndef __powerpc64__
-#define __NR_fadvise64_64      254
-#endif
-#define __NR_rtas              255
-#define __NR_sys_debug_setcontext 256
-/* Number 257 is reserved for vserver */
-#define __NR_migrate_pages     258
-#define __NR_mbind             259
-#define __NR_get_mempolicy     260
-#define __NR_set_mempolicy     261
-#define __NR_mq_open           262
-#define __NR_mq_unlink         263
-#define __NR_mq_timedsend      264
-#define __NR_mq_timedreceive   265
-#define __NR_mq_notify         266
-#define __NR_mq_getsetattr     267
-#define __NR_kexec_load                268
-#define __NR_add_key           269
-#define __NR_request_key       270
-#define __NR_keyctl            271
-#define __NR_waitid            272
-#define __NR_ioprio_set                273
-#define __NR_ioprio_get                274
-#define __NR_inotify_init      275
-#define __NR_inotify_add_watch 276
-#define __NR_inotify_rm_watch  277
-#define __NR_spu_run           278
-#define __NR_spu_create                279
-#define __NR_pselect6          280
-#define __NR_ppoll             281
-#define __NR_unshare           282
-#define __NR_splice            283
-#define __NR_tee               284
-#define __NR_vmsplice          285
-#define __NR_openat            286
-#define __NR_mkdirat           287
-#define __NR_mknodat           288
-#define __NR_fchownat          289
-#define __NR_futimesat         290
-#ifdef __powerpc64__
-#define __NR_newfstatat                291
-#else
-#define __NR_fstatat64         291
-#endif
-#define __NR_unlinkat          292
-#define __NR_renameat          293
-#define __NR_linkat            294
-#define __NR_symlinkat         295
-#define __NR_readlinkat                296
-#define __NR_fchmodat          297
-#define __NR_faccessat         298
-#define __NR_get_robust_list   299
-#define __NR_set_robust_list   300
-#define __NR_move_pages                301
-#define __NR_getcpu            302
-#define __NR_epoll_pwait       303
-#define __NR_utimensat         304
-#define __NR_signalfd          305
-#define __NR_timerfd_create    306
-#define __NR_eventfd           307
-#define __NR_sync_file_range2  308
-#define __NR_fallocate         309
-#define __NR_subpage_prot      310
-#define __NR_timerfd_settime   311
-#define __NR_timerfd_gettime   312
-#define __NR_signalfd4         313
-#define __NR_eventfd2          314
-#define __NR_epoll_create1     315
-#define __NR_dup3              316
-#define __NR_pipe2             317
-#define __NR_inotify_init1     318
-#define __NR_perf_event_open   319
-#define __NR_preadv            320
-#define __NR_pwritev           321
-#define __NR_rt_tgsigqueueinfo 322
-#define __NR_fanotify_init     323
-#define __NR_fanotify_mark     324
-#define __NR_prlimit64         325
-#define __NR_socket            326
-#define __NR_bind              327
-#define __NR_connect           328
-#define __NR_listen            329
-#define __NR_accept            330
-#define __NR_getsockname       331
-#define __NR_getpeername       332
-#define __NR_socketpair                333
-#define __NR_send              334
-#define __NR_sendto            335
-#define __NR_recv              336
-#define __NR_recvfrom          337
-#define __NR_shutdown          338
-#define __NR_setsockopt                339
-#define __NR_getsockopt                340
-#define __NR_sendmsg           341
-#define __NR_recvmsg           342
-#define __NR_recvmmsg          343
-#define __NR_accept4           344
-#define __NR_name_to_handle_at 345
-#define __NR_open_by_handle_at 346
-#define __NR_clock_adjtime     347
-#define __NR_syncfs            348
-#define __NR_sendmmsg          349
-#define __NR_setns             350
-#define __NR_process_vm_readv  351
-#define __NR_process_vm_writev 352
-#define __NR_finit_module      353
-#define __NR_kcmp              354
-#define __NR_sched_setattr     355
-#define __NR_sched_getattr     356
-#define __NR_renameat2         357
-#define __NR_seccomp           358
-#define __NR_getrandom         359
-#define __NR_memfd_create      360
-#define __NR_bpf               361
-#define __NR_execveat          362
-#define __NR_switch_endian     363
-#define __NR_userfaultfd       364
-#define __NR_membarrier                365
-#define __NR_mlock2            378
-#define __NR_copy_file_range   379
-#define __NR_preadv2           380
-#define __NR_pwritev2          381
-#define __NR_kexec_file_load   382
-#define __NR_statx             383
-#define __NR_pkey_alloc                384
-#define __NR_pkey_free         385
-#define __NR_pkey_mprotect     386
-#define __NR_rseq              387
-#define __NR_io_pgetevents     388
-
-#endif /* _UAPI_ASM_POWERPC_UNISTD_H_ */
diff --git a/tools/arch/riscv/include/uapi/asm/bitsperlong.h b/tools/arch/riscv/include/uapi/asm/bitsperlong.h
new file mode 100644 (file)
index 0000000..0b3cb52
--- /dev/null
@@ -0,0 +1,25 @@
+/*
+ * Copyright (C) 2012 ARM Ltd.
+ * Copyright (C) 2015 Regents of the University of California
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2 as
+ * published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#ifndef _UAPI_ASM_RISCV_BITSPERLONG_H
+#define _UAPI_ASM_RISCV_BITSPERLONG_H
+
+#define __BITS_PER_LONG (__SIZEOF_POINTER__ * 8)
+
+#include <asm-generic/bitsperlong.h>
+
+#endif /* _UAPI_ASM_RISCV_BITSPERLONG_H */
index 28c4a50..6d61225 100644 (file)
 #define X86_FEATURE_CLZERO             (13*32+ 0) /* CLZERO instruction */
 #define X86_FEATURE_IRPERF             (13*32+ 1) /* Instructions Retired Count */
 #define X86_FEATURE_XSAVEERPTR         (13*32+ 2) /* Always save/restore FP error pointers */
+#define X86_FEATURE_WBNOINVD           (13*32+ 9) /* WBNOINVD instruction */
 #define X86_FEATURE_AMD_IBPB           (13*32+12) /* "" Indirect Branch Prediction Barrier */
 #define X86_FEATURE_AMD_IBRS           (13*32+14) /* "" Indirect Branch Restricted Speculation */
 #define X86_FEATURE_AMD_STIBP          (13*32+15) /* "" Single Thread Indirect Branch Predictors */
+#define X86_FEATURE_AMD_STIBP_ALWAYS_ON        (13*32+17) /* "" Single Thread Indirect Branch Predictors always-on preferred */
 #define X86_FEATURE_AMD_SSBD           (13*32+24) /* "" Speculative Store Bypass Disable */
 #define X86_FEATURE_VIRT_SSBD          (13*32+25) /* Virtualized Speculative Store Bypass Disable */
 #define X86_FEATURE_AMD_SSB_NO         (13*32+26) /* "" Speculative Store Bypass is fixed in hardware. */
index 33833d1..a5ea841 100644 (file)
 # define DISABLE_MPX   (1<<(X86_FEATURE_MPX & 31))
 #endif
 
+#ifdef CONFIG_X86_SMAP
+# define DISABLE_SMAP  0
+#else
+# define DISABLE_SMAP  (1<<(X86_FEATURE_SMAP & 31))
+#endif
+
 #ifdef CONFIG_X86_INTEL_UMIP
 # define DISABLE_UMIP  0
 #else
@@ -68,7 +74,7 @@
 #define DISABLED_MASK6 0
 #define DISABLED_MASK7 (DISABLE_PTI)
 #define DISABLED_MASK8 0
-#define DISABLED_MASK9 (DISABLE_MPX)
+#define DISABLED_MASK9 (DISABLE_MPX|DISABLE_SMAP)
 #define DISABLED_MASK10        0
 #define DISABLED_MASK11        0
 #define DISABLED_MASK12        0
index 492f0f2..4ad1f08 100644 (file)
@@ -93,9 +93,16 @@ BFD_SRCS = jit_disasm.c
 SRCS = $(filter-out $(BFD_SRCS),$(wildcard *.c))
 
 ifeq ($(feature-libbfd),1)
+  LIBS += -lbfd -ldl -lopcodes
+else ifeq ($(feature-libbfd-liberty),1)
+  LIBS += -lbfd -ldl -lopcodes -liberty
+else ifeq ($(feature-libbfd-liberty-z),1)
+  LIBS += -lbfd -ldl -lopcodes -liberty -lz
+endif
+
+ifneq ($(filter -lbfd,$(LIBS)),)
 CFLAGS += -DHAVE_LIBBFD_SUPPORT
 SRCS += $(BFD_SRCS)
-LIBS += -lbfd -lopcodes
 endif
 
 OBJS = $(patsubst %.c,$(OUTPUT)%.o,$(SRCS)) $(OUTPUT)disasm.o
index 3f0629e..6ba5f56 100644 (file)
@@ -82,8 +82,6 @@ static void btf_dumper_bitfield(__u32 nr_bits, __u8 bit_offset,
        int bits_to_copy;
        __u64 print_num;
 
-       data += BITS_ROUNDDOWN_BYTES(bit_offset);
-       bit_offset = BITS_PER_BYTE_MASKED(bit_offset);
        bits_to_copy = bit_offset + nr_bits;
        bytes_to_copy = BITS_ROUNDUP_BYTES(bits_to_copy);
 
@@ -118,7 +116,9 @@ static void btf_dumper_int_bits(__u32 int_type, __u8 bit_offset,
         * BTF_INT_OFFSET() cannot exceed 64 bits.
         */
        total_bits_offset = bit_offset + BTF_INT_OFFSET(int_type);
-       btf_dumper_bitfield(nr_bits, total_bits_offset, data, jw,
+       data += BITS_ROUNDDOWN_BYTES(total_bits_offset);
+       bit_offset = BITS_PER_BYTE_MASKED(total_bits_offset);
+       btf_dumper_bitfield(nr_bits, bit_offset, data, jw,
                            is_plain_text);
 }
 
@@ -216,11 +216,12 @@ static int btf_dumper_struct(const struct btf_dumper *d, __u32 type_id,
                }
 
                jsonw_name(d->jw, btf__name_by_offset(d->btf, m[i].name_off));
+               data_off = data + BITS_ROUNDDOWN_BYTES(bit_offset);
                if (bitfield_size) {
-                       btf_dumper_bitfield(bitfield_size, bit_offset,
-                                           data, d->jw, d->is_plain_text);
+                       btf_dumper_bitfield(bitfield_size,
+                                           BITS_PER_BYTE_MASKED(bit_offset),
+                                           data_off, d->jw, d->is_plain_text);
                } else {
-                       data_off = data + BITS_ROUNDDOWN_BYTES(bit_offset);
                        ret = btf_dumper_do_type(d, m[i].type,
                                                 BITS_PER_BYTE_MASKED(bit_offset),
                                                 data_off);
index 8974834..f7261fa 100644 (file)
@@ -297,10 +297,8 @@ char *get_fdinfo(int fd, const char *key)
        snprintf(path, sizeof(path), "/proc/self/fdinfo/%d", fd);
 
        fdi = fopen(path, "r");
-       if (!fdi) {
-               p_err("can't open fdinfo: %s", strerror(errno));
+       if (!fdi)
                return NULL;
-       }
 
        while ((n = getline(&line, &line_n, fdi)) > 0) {
                char *value;
@@ -313,7 +311,6 @@ char *get_fdinfo(int fd, const char *key)
 
                value = strchr(line, '\t');
                if (!value || !value[1]) {
-                       p_err("malformed fdinfo!?");
                        free(line);
                        return NULL;
                }
@@ -326,7 +323,6 @@ char *get_fdinfo(int fd, const char *key)
                return line;
        }
 
-       p_err("key '%s' not found in fdinfo", key);
        free(line);
        fclose(fdi);
        return NULL;
index bff7ee0..6046dca 100644 (file)
@@ -1,15 +1,10 @@
-// SPDX-License-Identifier: (GPL-2.0-only OR BSD-2-Clause)
+// SPDX-License-Identifier: (GPL-2.0-or-later OR BSD-2-Clause)
 /*
  * Simple streaming JSON writer
  *
  * This takes care of the annoying bits of JSON syntax like the commas
  * after elements
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
  * Authors:    Stephen Hemminger <stephen@networkplumber.org>
  */
 
index c1ab51a..cb9a199 100644 (file)
@@ -5,11 +5,6 @@
  * This takes care of the annoying bits of JSON syntax like the commas
  * after elements
  *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version
- * 2 of the License, or (at your option) any later version.
- *
  * Authors:    Stephen Hemminger <stephen@networkplumber.org>
  */
 
index 2037e3d..1ef1ee2 100644 (file)
@@ -347,6 +347,20 @@ static char **parse_bytes(char **argv, const char *name, unsigned char *val,
        return argv + i;
 }
 
+/* on per cpu maps we must copy the provided value on all value instances */
+static void fill_per_cpu_value(struct bpf_map_info *info, void *value)
+{
+       unsigned int i, n, step;
+
+       if (!map_is_per_cpu(info->type))
+               return;
+
+       n = get_possible_cpus();
+       step = round_up(info->value_size, 8);
+       for (i = 1; i < n; i++)
+               memcpy(value + i * step, value, info->value_size);
+}
+
 static int parse_elem(char **argv, struct bpf_map_info *info,
                      void *key, void *value, __u32 key_size, __u32 value_size,
                      __u32 *flags, __u32 **value_fd)
@@ -426,6 +440,8 @@ static int parse_elem(char **argv, struct bpf_map_info *info,
                        argv = parse_bytes(argv, "value", value, value_size);
                        if (!argv)
                                return -1;
+
+                       fill_per_cpu_value(info, value);
                }
 
                return parse_elem(argv, info, key, NULL, key_size, value_size,
@@ -497,10 +513,9 @@ static int show_map_close_json(int fd, struct bpf_map_info *info)
                                jsonw_uint_field(json_wtr, "owner_prog_type",
                                                 prog_type);
                }
-               if (atoi(owner_jited))
-                       jsonw_bool_field(json_wtr, "owner_jited", true);
-               else
-                       jsonw_bool_field(json_wtr, "owner_jited", false);
+               if (owner_jited)
+                       jsonw_bool_field(json_wtr, "owner_jited",
+                                        !!atoi(owner_jited));
 
                free(owner_prog_type);
                free(owner_jited);
@@ -553,7 +568,8 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info)
                char *owner_prog_type = get_fdinfo(fd, "owner_prog_type");
                char *owner_jited = get_fdinfo(fd, "owner_jited");
 
-               printf("\n\t");
+               if (owner_prog_type || owner_jited)
+                       printf("\n\t");
                if (owner_prog_type) {
                        unsigned int prog_type = atoi(owner_prog_type);
 
@@ -563,10 +579,9 @@ static int show_map_close_plain(int fd, struct bpf_map_info *info)
                        else
                                printf("owner_prog_type %d  ", prog_type);
                }
-               if (atoi(owner_jited))
-                       printf("owner jited");
-               else
-                       printf("owner not jited");
+               if (owner_jited)
+                       printf("owner%s jited",
+                              atoi(owner_jited) ? "" : " not");
 
                free(owner_prog_type);
                free(owner_jited);
index 2d1bb7d..b54ed82 100644 (file)
@@ -78,13 +78,14 @@ static void print_boot_time(__u64 nsecs, char *buf, unsigned int size)
 
 static int prog_fd_by_tag(unsigned char *tag)
 {
-       struct bpf_prog_info info = {};
-       __u32 len = sizeof(info);
        unsigned int id = 0;
        int err;
        int fd;
 
        while (true) {
+               struct bpf_prog_info info = {};
+               __u32 len = sizeof(info);
+
                err = bpf_prog_get_next_id(id, &id);
                if (err) {
                        p_err("%s", strerror(errno));
index 3040830..8454566 100644 (file)
@@ -330,7 +330,7 @@ static const struct option longopts[] = {
 
 int main(int argc, char **argv)
 {
-       unsigned long long num_loops = 2;
+       long long num_loops = 2;
        unsigned long timedelay = 1000000;
        unsigned long buf_len = 128;
 
index c7f3321..d901272 100644 (file)
@@ -738,9 +738,11 @@ __SYSCALL(__NR_statx,     sys_statx)
 __SC_COMP(__NR_io_pgetevents, sys_io_pgetevents, compat_sys_io_pgetevents)
 #define __NR_rseq 293
 __SYSCALL(__NR_rseq, sys_rseq)
+#define __NR_kexec_file_load 294
+__SYSCALL(__NR_kexec_file_load,     sys_kexec_file_load)
 
 #undef __NR_syscalls
-#define __NR_syscalls 294
+#define __NR_syscalls 295
 
 /*
  * 32 bit systems traditionally used different
index 8dd6aef..57aaeaf 100644 (file)
 #include "../../arch/mips/include/uapi/asm/bitsperlong.h"
 #elif defined(__ia64__)
 #include "../../arch/ia64/include/uapi/asm/bitsperlong.h"
+#elif defined(__riscv)
+#include "../../arch/riscv/include/uapi/asm/bitsperlong.h"
+#elif defined(__alpha__)
+#include "../../arch/alpha/include/uapi/asm/bitsperlong.h"
 #else
 #include <asm-generic/bitsperlong.h>
 #endif
index a4446f4..298b2e1 100644 (file)
@@ -412,6 +412,14 @@ typedef struct drm_i915_irq_wait {
        int irq_seq;
 } drm_i915_irq_wait_t;
 
+/*
+ * Different modes of per-process Graphics Translation Table,
+ * see I915_PARAM_HAS_ALIASING_PPGTT
+ */
+#define I915_GEM_PPGTT_NONE    0
+#define I915_GEM_PPGTT_ALIASING        1
+#define I915_GEM_PPGTT_FULL    2
+
 /* Ioctl to query kernel params:
  */
 #define I915_PARAM_IRQ_ACTIVE            1
index a441ea1..121e82c 100644 (file)
 #include <linux/ioctl.h>
 #include <linux/types.h>
 
+/* Use of MS_* flags within the kernel is restricted to core mount(2) code. */
+#if !defined(__KERNEL__)
+#include <linux/mount.h>
+#endif
+
 /*
  * It's silly to have NR_OPEN bigger than NR_FILE, but you can change
  * the file limit at runtime and only root can increase the per-process
@@ -101,57 +106,6 @@ struct inodes_stat_t {
 
 #define NR_FILE  8192  /* this can well be larger on a larger system */
 
-
-/*
- * These are the fs-independent mount-flags: up to 32 flags are supported
- */
-#define MS_RDONLY       1      /* Mount read-only */
-#define MS_NOSUID       2      /* Ignore suid and sgid bits */
-#define MS_NODEV        4      /* Disallow access to device special files */
-#define MS_NOEXEC       8      /* Disallow program execution */
-#define MS_SYNCHRONOUS 16      /* Writes are synced at once */
-#define MS_REMOUNT     32      /* Alter flags of a mounted FS */
-#define MS_MANDLOCK    64      /* Allow mandatory locks on an FS */
-#define MS_DIRSYNC     128     /* Directory modifications are synchronous */
-#define MS_NOATIME     1024    /* Do not update access times. */
-#define MS_NODIRATIME  2048    /* Do not update directory access times */
-#define MS_BIND                4096
-#define MS_MOVE                8192
-#define MS_REC         16384
-#define MS_VERBOSE     32768   /* War is peace. Verbosity is silence.
-                                  MS_VERBOSE is deprecated. */
-#define MS_SILENT      32768
-#define MS_POSIXACL    (1<<16) /* VFS does not apply the umask */
-#define MS_UNBINDABLE  (1<<17) /* change to unbindable */
-#define MS_PRIVATE     (1<<18) /* change to private */
-#define MS_SLAVE       (1<<19) /* change to slave */
-#define MS_SHARED      (1<<20) /* change to shared */
-#define MS_RELATIME    (1<<21) /* Update atime relative to mtime/ctime. */
-#define MS_KERNMOUNT   (1<<22) /* this is a kern_mount call */
-#define MS_I_VERSION   (1<<23) /* Update inode I_version field */
-#define MS_STRICTATIME (1<<24) /* Always perform atime updates */
-#define MS_LAZYTIME    (1<<25) /* Update the on-disk [acm]times lazily */
-
-/* These sb flags are internal to the kernel */
-#define MS_SUBMOUNT     (1<<26)
-#define MS_NOREMOTELOCK        (1<<27)
-#define MS_NOSEC       (1<<28)
-#define MS_BORN                (1<<29)
-#define MS_ACTIVE      (1<<30)
-#define MS_NOUSER      (1<<31)
-
-/*
- * Superblock flags that can be altered by MS_REMOUNT
- */
-#define MS_RMT_MASK    (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|\
-                        MS_LAZYTIME)
-
-/*
- * Old magic mount flag and mask
- */
-#define MS_MGC_VAL 0xC0ED0000
-#define MS_MGC_MSK 0xffff0000
-
 /*
  * Structure for FS_IOC_FSGETXATTR[A] and FS_IOC_FSSETXATTR.
  */
@@ -269,7 +223,8 @@ struct fsxattr {
 #define FS_POLICY_FLAGS_PAD_16         0x02
 #define FS_POLICY_FLAGS_PAD_32         0x03
 #define FS_POLICY_FLAGS_PAD_MASK       0x03
-#define FS_POLICY_FLAGS_VALID          0x03
+#define FS_POLICY_FLAG_DIRECT_KEY      0x04    /* use master key directly */
+#define FS_POLICY_FLAGS_VALID          0x07
 
 /* Encryption algorithms */
 #define FS_ENCRYPTION_MODE_INVALID             0
@@ -281,6 +236,7 @@ struct fsxattr {
 #define FS_ENCRYPTION_MODE_AES_128_CTS         6
 #define FS_ENCRYPTION_MODE_SPECK128_256_XTS    7 /* Removed, do not use. */
 #define FS_ENCRYPTION_MODE_SPECK128_256_CTS    8 /* Removed, do not use. */
+#define FS_ENCRYPTION_MODE_ADIANTUM            9
 
 struct fscrypt_policy {
        __u8 version;
index 1debfa4..d653382 100644 (file)
@@ -288,6 +288,7 @@ enum {
        IFLA_BR_MCAST_IGMP_VERSION,
        IFLA_BR_MCAST_MLD_VERSION,
        IFLA_BR_VLAN_STATS_PER_PORT,
+       IFLA_BR_MULTI_BOOLOPT,
        __IFLA_BR_MAX,
 };
 
@@ -533,6 +534,7 @@ enum {
        IFLA_VXLAN_LABEL,
        IFLA_VXLAN_GPE,
        IFLA_VXLAN_TTL_INHERIT,
+       IFLA_VXLAN_DF,
        __IFLA_VXLAN_MAX
 };
 #define IFLA_VXLAN_MAX (__IFLA_VXLAN_MAX - 1)
@@ -542,6 +544,14 @@ struct ifla_vxlan_port_range {
        __be16  high;
 };
 
+enum ifla_vxlan_df {
+       VXLAN_DF_UNSET = 0,
+       VXLAN_DF_SET,
+       VXLAN_DF_INHERIT,
+       __VXLAN_DF_END,
+       VXLAN_DF_MAX = __VXLAN_DF_END - 1,
+};
+
 /* GENEVE section */
 enum {
        IFLA_GENEVE_UNSPEC,
@@ -557,10 +567,19 @@ enum {
        IFLA_GENEVE_UDP_ZERO_CSUM6_RX,
        IFLA_GENEVE_LABEL,
        IFLA_GENEVE_TTL_INHERIT,
+       IFLA_GENEVE_DF,
        __IFLA_GENEVE_MAX
 };
 #define IFLA_GENEVE_MAX        (__IFLA_GENEVE_MAX - 1)
 
+enum ifla_geneve_df {
+       GENEVE_DF_UNSET = 0,
+       GENEVE_DF_SET,
+       GENEVE_DF_INHERIT,
+       __GENEVE_DF_END,
+       GENEVE_DF_MAX = __GENEVE_DF_END - 1,
+};
+
 /* PPP section */
 enum {
        IFLA_PPP_UNSPEC,
index 48e8a22..a55cb8b 100644 (file)
@@ -266,10 +266,14 @@ struct sockaddr_in {
 
 #define        IN_CLASSD(a)            ((((long int) (a)) & 0xf0000000) == 0xe0000000)
 #define        IN_MULTICAST(a)         IN_CLASSD(a)
-#define IN_MULTICAST_NET       0xF0000000
+#define        IN_MULTICAST_NET        0xe0000000
 
-#define        IN_EXPERIMENTAL(a)      ((((long int) (a)) & 0xf0000000) == 0xf0000000)
-#define        IN_BADCLASS(a)          IN_EXPERIMENTAL((a))
+#define        IN_BADCLASS(a)          (((long int) (a) ) == (long int)0xffffffff)
+#define        IN_EXPERIMENTAL(a)      IN_BADCLASS((a))
+
+#define        IN_CLASSE(a)            ((((long int) (a)) & 0xf0000000) == 0xf0000000)
+#define        IN_CLASSE_NET           0xffffffff
+#define        IN_CLASSE_NSHIFT        0
 
 /* Address to accept any incoming messages. */
 #define        INADDR_ANY              ((unsigned long int) 0x00000000)
index 2b7a652..6d4ea4b 100644 (file)
@@ -492,6 +492,17 @@ struct kvm_dirty_log {
        };
 };
 
+/* for KVM_CLEAR_DIRTY_LOG */
+struct kvm_clear_dirty_log {
+       __u32 slot;
+       __u32 num_pages;
+       __u64 first_page;
+       union {
+               void __user *dirty_bitmap; /* one bit per page */
+               __u64 padding2;
+       };
+};
+
 /* for KVM_SET_SIGNAL_MASK */
 struct kvm_signal_mask {
        __u32 len;
@@ -975,6 +986,8 @@ struct kvm_ppc_resize_hpt {
 #define KVM_CAP_HYPERV_ENLIGHTENED_VMCS 163
 #define KVM_CAP_EXCEPTION_PAYLOAD 164
 #define KVM_CAP_ARM_VM_IPA_SIZE 165
+#define KVM_CAP_MANUAL_DIRTY_LOG_PROTECT 166
+#define KVM_CAP_HYPERV_CPUID 167
 
 #ifdef KVM_CAP_IRQ_ROUTING
 
@@ -1421,6 +1434,12 @@ struct kvm_enc_region {
 #define KVM_GET_NESTED_STATE         _IOWR(KVMIO, 0xbe, struct kvm_nested_state)
 #define KVM_SET_NESTED_STATE         _IOW(KVMIO,  0xbf, struct kvm_nested_state)
 
+/* Available with KVM_CAP_MANUAL_DIRTY_LOG_PROTECT */
+#define KVM_CLEAR_DIRTY_LOG          _IOWR(KVMIO, 0xc0, struct kvm_clear_dirty_log)
+
+/* Available with KVM_CAP_HYPERV_CPUID */
+#define KVM_GET_SUPPORTED_HV_CPUID _IOWR(KVMIO, 0xc1, struct kvm_cpuid2)
+
 /* Secure Encrypted Virtualization command */
 enum sev_cmd_id {
        /* Guest initialization commands */
diff --git a/tools/include/uapi/linux/mount.h b/tools/include/uapi/linux/mount.h
new file mode 100644 (file)
index 0000000..3f9ec42
--- /dev/null
@@ -0,0 +1,58 @@
+#ifndef _UAPI_LINUX_MOUNT_H
+#define _UAPI_LINUX_MOUNT_H
+
+/*
+ * These are the fs-independent mount-flags: up to 32 flags are supported
+ *
+ * Usage of these is restricted within the kernel to core mount(2) code and
+ * callers of sys_mount() only.  Filesystems should be using the SB_*
+ * equivalent instead.
+ */
+#define MS_RDONLY       1      /* Mount read-only */
+#define MS_NOSUID       2      /* Ignore suid and sgid bits */
+#define MS_NODEV        4      /* Disallow access to device special files */
+#define MS_NOEXEC       8      /* Disallow program execution */
+#define MS_SYNCHRONOUS 16      /* Writes are synced at once */
+#define MS_REMOUNT     32      /* Alter flags of a mounted FS */
+#define MS_MANDLOCK    64      /* Allow mandatory locks on an FS */
+#define MS_DIRSYNC     128     /* Directory modifications are synchronous */
+#define MS_NOATIME     1024    /* Do not update access times. */
+#define MS_NODIRATIME  2048    /* Do not update directory access times */
+#define MS_BIND                4096
+#define MS_MOVE                8192
+#define MS_REC         16384
+#define MS_VERBOSE     32768   /* War is peace. Verbosity is silence.
+                                  MS_VERBOSE is deprecated. */
+#define MS_SILENT      32768
+#define MS_POSIXACL    (1<<16) /* VFS does not apply the umask */
+#define MS_UNBINDABLE  (1<<17) /* change to unbindable */
+#define MS_PRIVATE     (1<<18) /* change to private */
+#define MS_SLAVE       (1<<19) /* change to slave */
+#define MS_SHARED      (1<<20) /* change to shared */
+#define MS_RELATIME    (1<<21) /* Update atime relative to mtime/ctime. */
+#define MS_KERNMOUNT   (1<<22) /* this is a kern_mount call */
+#define MS_I_VERSION   (1<<23) /* Update inode I_version field */
+#define MS_STRICTATIME (1<<24) /* Always perform atime updates */
+#define MS_LAZYTIME    (1<<25) /* Update the on-disk [acm]times lazily */
+
+/* These sb flags are internal to the kernel */
+#define MS_SUBMOUNT     (1<<26)
+#define MS_NOREMOTELOCK        (1<<27)
+#define MS_NOSEC       (1<<28)
+#define MS_BORN                (1<<29)
+#define MS_ACTIVE      (1<<30)
+#define MS_NOUSER      (1<<31)
+
+/*
+ * Superblock flags that can be altered by MS_REMOUNT
+ */
+#define MS_RMT_MASK    (MS_RDONLY|MS_SYNCHRONOUS|MS_MANDLOCK|MS_I_VERSION|\
+                        MS_LAZYTIME)
+
+/*
+ * Old magic mount flag and mask
+ */
+#define MS_MGC_VAL 0xC0ED0000
+#define MS_MGC_MSK 0xffff0000
+
+#endif /* _UAPI_LINUX_MOUNT_H */
diff --git a/tools/include/uapi/linux/pkt_sched.h b/tools/include/uapi/linux/pkt_sched.h
new file mode 100644 (file)
index 0000000..0d18b1d
--- /dev/null
@@ -0,0 +1,1163 @@
+/* SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note */
+#ifndef __LINUX_PKT_SCHED_H
+#define __LINUX_PKT_SCHED_H
+
+#include <linux/types.h>
+
+/* Logical priority bands not depending on specific packet scheduler.
+   Every scheduler will map them to real traffic classes, if it has
+   no more precise mechanism to classify packets.
+
+   These numbers have no special meaning, though their coincidence
+   with obsolete IPv6 values is not occasional :-). New IPv6 drafts
+   preferred full anarchy inspired by diffserv group.
+
+   Note: TC_PRIO_BESTEFFORT does not mean that it is the most unhappy
+   class, actually, as rule it will be handled with more care than
+   filler or even bulk.
+ */
+
+#define TC_PRIO_BESTEFFORT             0
+#define TC_PRIO_FILLER                 1
+#define TC_PRIO_BULK                   2
+#define TC_PRIO_INTERACTIVE_BULK       4
+#define TC_PRIO_INTERACTIVE            6
+#define TC_PRIO_CONTROL                        7
+
+#define TC_PRIO_MAX                    15
+
+/* Generic queue statistics, available for all the elements.
+   Particular schedulers may have also their private records.
+ */
+
+struct tc_stats {
+       __u64   bytes;                  /* Number of enqueued bytes */
+       __u32   packets;                /* Number of enqueued packets   */
+       __u32   drops;                  /* Packets dropped because of lack of resources */
+       __u32   overlimits;             /* Number of throttle events when this
+                                        * flow goes out of allocated bandwidth */
+       __u32   bps;                    /* Current flow byte rate */
+       __u32   pps;                    /* Current flow packet rate */
+       __u32   qlen;
+       __u32   backlog;
+};
+
+struct tc_estimator {
+       signed char     interval;
+       unsigned char   ewma_log;
+};
+
+/* "Handles"
+   ---------
+
+    All the traffic control objects have 32bit identifiers, or "handles".
+
+    They can be considered as opaque numbers from user API viewpoint,
+    but actually they always consist of two fields: major and
+    minor numbers, which are interpreted by kernel specially,
+    that may be used by applications, though not recommended.
+
+    F.e. qdisc handles always have minor number equal to zero,
+    classes (or flows) have major equal to parent qdisc major, and
+    minor uniquely identifying class inside qdisc.
+
+    Macros to manipulate handles:
+ */
+
+#define TC_H_MAJ_MASK (0xFFFF0000U)
+#define TC_H_MIN_MASK (0x0000FFFFU)
+#define TC_H_MAJ(h) ((h)&TC_H_MAJ_MASK)
+#define TC_H_MIN(h) ((h)&TC_H_MIN_MASK)
+#define TC_H_MAKE(maj,min) (((maj)&TC_H_MAJ_MASK)|((min)&TC_H_MIN_MASK))
+
+#define TC_H_UNSPEC    (0U)
+#define TC_H_ROOT      (0xFFFFFFFFU)
+#define TC_H_INGRESS    (0xFFFFFFF1U)
+#define TC_H_CLSACT    TC_H_INGRESS
+
+#define TC_H_MIN_PRIORITY      0xFFE0U
+#define TC_H_MIN_INGRESS       0xFFF2U
+#define TC_H_MIN_EGRESS                0xFFF3U
+
+/* Need to corrospond to iproute2 tc/tc_core.h "enum link_layer" */
+enum tc_link_layer {
+       TC_LINKLAYER_UNAWARE, /* Indicate unaware old iproute2 util */
+       TC_LINKLAYER_ETHERNET,
+       TC_LINKLAYER_ATM,
+};
+#define TC_LINKLAYER_MASK 0x0F /* limit use to lower 4 bits */
+
+struct tc_ratespec {
+       unsigned char   cell_log;
+       __u8            linklayer; /* lower 4 bits */
+       unsigned short  overhead;
+       short           cell_align;
+       unsigned short  mpu;
+       __u32           rate;
+};
+
+#define TC_RTAB_SIZE   1024
+
+struct tc_sizespec {
+       unsigned char   cell_log;
+       unsigned char   size_log;
+       short           cell_align;
+       int             overhead;
+       unsigned int    linklayer;
+       unsigned int    mpu;
+       unsigned int    mtu;
+       unsigned int    tsize;
+};
+
+enum {
+       TCA_STAB_UNSPEC,
+       TCA_STAB_BASE,
+       TCA_STAB_DATA,
+       __TCA_STAB_MAX
+};
+
+#define TCA_STAB_MAX (__TCA_STAB_MAX - 1)
+
+/* FIFO section */
+
+struct tc_fifo_qopt {
+       __u32   limit;  /* Queue length: bytes for bfifo, packets for pfifo */
+};
+
+/* SKBPRIO section */
+
+/*
+ * Priorities go from zero to (SKBPRIO_MAX_PRIORITY - 1).
+ * SKBPRIO_MAX_PRIORITY should be at least 64 in order for skbprio to be able
+ * to map one to one the DS field of IPV4 and IPV6 headers.
+ * Memory allocation grows linearly with SKBPRIO_MAX_PRIORITY.
+ */
+
+#define SKBPRIO_MAX_PRIORITY 64
+
+struct tc_skbprio_qopt {
+       __u32   limit;          /* Queue length in packets. */
+};
+
+/* PRIO section */
+
+#define TCQ_PRIO_BANDS 16
+#define TCQ_MIN_PRIO_BANDS 2
+
+struct tc_prio_qopt {
+       int     bands;                  /* Number of bands */
+       __u8    priomap[TC_PRIO_MAX+1]; /* Map: logical priority -> PRIO band */
+};
+
+/* MULTIQ section */
+
+struct tc_multiq_qopt {
+       __u16   bands;                  /* Number of bands */
+       __u16   max_bands;              /* Maximum number of queues */
+};
+
+/* PLUG section */
+
+#define TCQ_PLUG_BUFFER                0
+#define TCQ_PLUG_RELEASE_ONE           1
+#define TCQ_PLUG_RELEASE_INDEFINITE    2
+#define TCQ_PLUG_LIMIT                 3
+
+struct tc_plug_qopt {
+       /* TCQ_PLUG_BUFFER: Inset a plug into the queue and
+        *  buffer any incoming packets
+        * TCQ_PLUG_RELEASE_ONE: Dequeue packets from queue head
+        *   to beginning of the next plug.
+        * TCQ_PLUG_RELEASE_INDEFINITE: Dequeue all packets from queue.
+        *   Stop buffering packets until the next TCQ_PLUG_BUFFER
+        *   command is received (just act as a pass-thru queue).
+        * TCQ_PLUG_LIMIT: Increase/decrease queue size
+        */
+       int             action;
+       __u32           limit;
+};
+
+/* TBF section */
+
+struct tc_tbf_qopt {
+       struct tc_ratespec rate;
+       struct tc_ratespec peakrate;
+       __u32           limit;
+       __u32           buffer;
+       __u32           mtu;
+};
+
+enum {
+       TCA_TBF_UNSPEC,
+       TCA_TBF_PARMS,
+       TCA_TBF_RTAB,
+       TCA_TBF_PTAB,
+       TCA_TBF_RATE64,
+       TCA_TBF_PRATE64,
+       TCA_TBF_BURST,
+       TCA_TBF_PBURST,
+       TCA_TBF_PAD,
+       __TCA_TBF_MAX,
+};
+
+#define TCA_TBF_MAX (__TCA_TBF_MAX - 1)
+
+
+/* TEQL section */
+
+/* TEQL does not require any parameters */
+
+/* SFQ section */
+
+struct tc_sfq_qopt {
+       unsigned        quantum;        /* Bytes per round allocated to flow */
+       int             perturb_period; /* Period of hash perturbation */
+       __u32           limit;          /* Maximal packets in queue */
+       unsigned        divisor;        /* Hash divisor  */
+       unsigned        flows;          /* Maximal number of flows  */
+};
+
+struct tc_sfqred_stats {
+       __u32           prob_drop;      /* Early drops, below max threshold */
+       __u32           forced_drop;    /* Early drops, after max threshold */
+       __u32           prob_mark;      /* Marked packets, below max threshold */
+       __u32           forced_mark;    /* Marked packets, after max threshold */
+       __u32           prob_mark_head; /* Marked packets, below max threshold */
+       __u32           forced_mark_head;/* Marked packets, after max threshold */
+};
+
+struct tc_sfq_qopt_v1 {
+       struct tc_sfq_qopt v0;
+       unsigned int    depth;          /* max number of packets per flow */
+       unsigned int    headdrop;
+/* SFQRED parameters */
+       __u32           limit;          /* HARD maximal flow queue length (bytes) */
+       __u32           qth_min;        /* Min average length threshold (bytes) */
+       __u32           qth_max;        /* Max average length threshold (bytes) */
+       unsigned char   Wlog;           /* log(W)               */
+       unsigned char   Plog;           /* log(P_max/(qth_max-qth_min)) */
+       unsigned char   Scell_log;      /* cell size for idle damping */
+       unsigned char   flags;
+       __u32           max_P;          /* probability, high resolution */
+/* SFQRED stats */
+       struct tc_sfqred_stats stats;
+};
+
+
+struct tc_sfq_xstats {
+       __s32           allot;
+};
+
+/* RED section */
+
+enum {
+       TCA_RED_UNSPEC,
+       TCA_RED_PARMS,
+       TCA_RED_STAB,
+       TCA_RED_MAX_P,
+       __TCA_RED_MAX,
+};
+
+#define TCA_RED_MAX (__TCA_RED_MAX - 1)
+
+struct tc_red_qopt {
+       __u32           limit;          /* HARD maximal queue length (bytes)    */
+       __u32           qth_min;        /* Min average length threshold (bytes) */
+       __u32           qth_max;        /* Max average length threshold (bytes) */
+       unsigned char   Wlog;           /* log(W)               */
+       unsigned char   Plog;           /* log(P_max/(qth_max-qth_min)) */
+       unsigned char   Scell_log;      /* cell size for idle damping */
+       unsigned char   flags;
+#define TC_RED_ECN             1
+#define TC_RED_HARDDROP                2
+#define TC_RED_ADAPTATIVE      4
+};
+
+struct tc_red_xstats {
+       __u32           early;          /* Early drops */
+       __u32           pdrop;          /* Drops due to queue limits */
+       __u32           other;          /* Drops due to drop() calls */
+       __u32           marked;         /* Marked packets */
+};
+
+/* GRED section */
+
+#define MAX_DPs 16
+
+enum {
+       TCA_GRED_UNSPEC,
+       TCA_GRED_PARMS,
+       TCA_GRED_STAB,
+       TCA_GRED_DPS,
+       TCA_GRED_MAX_P,
+       TCA_GRED_LIMIT,
+       TCA_GRED_VQ_LIST,       /* nested TCA_GRED_VQ_ENTRY */
+       __TCA_GRED_MAX,
+};
+
+#define TCA_GRED_MAX (__TCA_GRED_MAX - 1)
+
+enum {
+       TCA_GRED_VQ_ENTRY_UNSPEC,
+       TCA_GRED_VQ_ENTRY,      /* nested TCA_GRED_VQ_* */
+       __TCA_GRED_VQ_ENTRY_MAX,
+};
+#define TCA_GRED_VQ_ENTRY_MAX (__TCA_GRED_VQ_ENTRY_MAX - 1)
+
+enum {
+       TCA_GRED_VQ_UNSPEC,
+       TCA_GRED_VQ_PAD,
+       TCA_GRED_VQ_DP,                 /* u32 */
+       TCA_GRED_VQ_STAT_BYTES,         /* u64 */
+       TCA_GRED_VQ_STAT_PACKETS,       /* u32 */
+       TCA_GRED_VQ_STAT_BACKLOG,       /* u32 */
+       TCA_GRED_VQ_STAT_PROB_DROP,     /* u32 */
+       TCA_GRED_VQ_STAT_PROB_MARK,     /* u32 */
+       TCA_GRED_VQ_STAT_FORCED_DROP,   /* u32 */
+       TCA_GRED_VQ_STAT_FORCED_MARK,   /* u32 */
+       TCA_GRED_VQ_STAT_PDROP,         /* u32 */
+       TCA_GRED_VQ_STAT_OTHER,         /* u32 */
+       TCA_GRED_VQ_FLAGS,              /* u32 */
+       __TCA_GRED_VQ_MAX
+};
+
+#define TCA_GRED_VQ_MAX (__TCA_GRED_VQ_MAX - 1)
+
+struct tc_gred_qopt {
+       __u32           limit;        /* HARD maximal queue length (bytes)    */
+       __u32           qth_min;      /* Min average length threshold (bytes) */
+       __u32           qth_max;      /* Max average length threshold (bytes) */
+       __u32           DP;           /* up to 2^32 DPs */
+       __u32           backlog;
+       __u32           qave;
+       __u32           forced;
+       __u32           early;
+       __u32           other;
+       __u32           pdrop;
+       __u8            Wlog;         /* log(W)               */
+       __u8            Plog;         /* log(P_max/(qth_max-qth_min)) */
+       __u8            Scell_log;    /* cell size for idle damping */
+       __u8            prio;         /* prio of this VQ */
+       __u32           packets;
+       __u32           bytesin;
+};
+
+/* gred setup */
+struct tc_gred_sopt {
+       __u32           DPs;
+       __u32           def_DP;
+       __u8            grio;
+       __u8            flags;
+       __u16           pad1;
+};
+
+/* CHOKe section */
+
+enum {
+       TCA_CHOKE_UNSPEC,
+       TCA_CHOKE_PARMS,
+       TCA_CHOKE_STAB,
+       TCA_CHOKE_MAX_P,
+       __TCA_CHOKE_MAX,
+};
+
+#define TCA_CHOKE_MAX (__TCA_CHOKE_MAX - 1)
+
+struct tc_choke_qopt {
+       __u32           limit;          /* Hard queue length (packets)  */
+       __u32           qth_min;        /* Min average threshold (packets) */
+       __u32           qth_max;        /* Max average threshold (packets) */
+       unsigned char   Wlog;           /* log(W)               */
+       unsigned char   Plog;           /* log(P_max/(qth_max-qth_min)) */
+       unsigned char   Scell_log;      /* cell size for idle damping */
+       unsigned char   flags;          /* see RED flags */
+};
+
+struct tc_choke_xstats {
+       __u32           early;          /* Early drops */
+       __u32           pdrop;          /* Drops due to queue limits */
+       __u32           other;          /* Drops due to drop() calls */
+       __u32           marked;         /* Marked packets */
+       __u32           matched;        /* Drops due to flow match */
+};
+
+/* HTB section */
+#define TC_HTB_NUMPRIO         8
+#define TC_HTB_MAXDEPTH                8
+#define TC_HTB_PROTOVER                3 /* the same as HTB and TC's major */
+
+struct tc_htb_opt {
+       struct tc_ratespec      rate;
+       struct tc_ratespec      ceil;
+       __u32   buffer;
+       __u32   cbuffer;
+       __u32   quantum;
+       __u32   level;          /* out only */
+       __u32   prio;
+};
+struct tc_htb_glob {
+       __u32 version;          /* to match HTB/TC */
+       __u32 rate2quantum;     /* bps->quantum divisor */
+       __u32 defcls;           /* default class number */
+       __u32 debug;            /* debug flags */
+
+       /* stats */
+       __u32 direct_pkts; /* count of non shaped packets */
+};
+enum {
+       TCA_HTB_UNSPEC,
+       TCA_HTB_PARMS,
+       TCA_HTB_INIT,
+       TCA_HTB_CTAB,
+       TCA_HTB_RTAB,
+       TCA_HTB_DIRECT_QLEN,
+       TCA_HTB_RATE64,
+       TCA_HTB_CEIL64,
+       TCA_HTB_PAD,
+       __TCA_HTB_MAX,
+};
+
+#define TCA_HTB_MAX (__TCA_HTB_MAX - 1)
+
+struct tc_htb_xstats {
+       __u32 lends;
+       __u32 borrows;
+       __u32 giants;   /* unused since 'Make HTB scheduler work with TSO.' */
+       __s32 tokens;
+       __s32 ctokens;
+};
+
+/* HFSC section */
+
+struct tc_hfsc_qopt {
+       __u16   defcls;         /* default class */
+};
+
+struct tc_service_curve {
+       __u32   m1;             /* slope of the first segment in bps */
+       __u32   d;              /* x-projection of the first segment in us */
+       __u32   m2;             /* slope of the second segment in bps */
+};
+
+struct tc_hfsc_stats {
+       __u64   work;           /* total work done */
+       __u64   rtwork;         /* work done by real-time criteria */
+       __u32   period;         /* current period */
+       __u32   level;          /* class level in hierarchy */
+};
+
+enum {
+       TCA_HFSC_UNSPEC,
+       TCA_HFSC_RSC,
+       TCA_HFSC_FSC,
+       TCA_HFSC_USC,
+       __TCA_HFSC_MAX,
+};
+
+#define TCA_HFSC_MAX (__TCA_HFSC_MAX - 1)
+
+
+/* CBQ section */
+
+#define TC_CBQ_MAXPRIO         8
+#define TC_CBQ_MAXLEVEL                8
+#define TC_CBQ_DEF_EWMA                5
+
+struct tc_cbq_lssopt {
+       unsigned char   change;
+       unsigned char   flags;
+#define TCF_CBQ_LSS_BOUNDED    1
+#define TCF_CBQ_LSS_ISOLATED   2
+       unsigned char   ewma_log;
+       unsigned char   level;
+#define TCF_CBQ_LSS_FLAGS      1
+#define TCF_CBQ_LSS_EWMA       2
+#define TCF_CBQ_LSS_MAXIDLE    4
+#define TCF_CBQ_LSS_MINIDLE    8
+#define TCF_CBQ_LSS_OFFTIME    0x10
+#define TCF_CBQ_LSS_AVPKT      0x20
+       __u32           maxidle;
+       __u32           minidle;
+       __u32           offtime;
+       __u32           avpkt;
+};
+
+struct tc_cbq_wrropt {
+       unsigned char   flags;
+       unsigned char   priority;
+       unsigned char   cpriority;
+       unsigned char   __reserved;
+       __u32           allot;
+       __u32           weight;
+};
+
+struct tc_cbq_ovl {
+       unsigned char   strategy;
+#define        TC_CBQ_OVL_CLASSIC      0
+#define        TC_CBQ_OVL_DELAY        1
+#define        TC_CBQ_OVL_LOWPRIO      2
+#define        TC_CBQ_OVL_DROP         3
+#define        TC_CBQ_OVL_RCLASSIC     4
+       unsigned char   priority2;
+       __u16           pad;
+       __u32           penalty;
+};
+
+struct tc_cbq_police {
+       unsigned char   police;
+       unsigned char   __res1;
+       unsigned short  __res2;
+};
+
+struct tc_cbq_fopt {
+       __u32           split;
+       __u32           defmap;
+       __u32           defchange;
+};
+
+struct tc_cbq_xstats {
+       __u32           borrows;
+       __u32           overactions;
+       __s32           avgidle;
+       __s32           undertime;
+};
+
+enum {
+       TCA_CBQ_UNSPEC,
+       TCA_CBQ_LSSOPT,
+       TCA_CBQ_WRROPT,
+       TCA_CBQ_FOPT,
+       TCA_CBQ_OVL_STRATEGY,
+       TCA_CBQ_RATE,
+       TCA_CBQ_RTAB,
+       TCA_CBQ_POLICE,
+       __TCA_CBQ_MAX,
+};
+
+#define TCA_CBQ_MAX    (__TCA_CBQ_MAX - 1)
+
+/* dsmark section */
+
+enum {
+       TCA_DSMARK_UNSPEC,
+       TCA_DSMARK_INDICES,
+       TCA_DSMARK_DEFAULT_INDEX,
+       TCA_DSMARK_SET_TC_INDEX,
+       TCA_DSMARK_MASK,
+       TCA_DSMARK_VALUE,
+       __TCA_DSMARK_MAX,
+};
+
+#define TCA_DSMARK_MAX (__TCA_DSMARK_MAX - 1)
+
+/* ATM  section */
+
+enum {
+       TCA_ATM_UNSPEC,
+       TCA_ATM_FD,             /* file/socket descriptor */
+       TCA_ATM_PTR,            /* pointer to descriptor - later */
+       TCA_ATM_HDR,            /* LL header */
+       TCA_ATM_EXCESS,         /* excess traffic class (0 for CLP)  */
+       TCA_ATM_ADDR,           /* PVC address (for output only) */
+       TCA_ATM_STATE,          /* VC state (ATM_VS_*; for output only) */
+       __TCA_ATM_MAX,
+};
+
+#define TCA_ATM_MAX    (__TCA_ATM_MAX - 1)
+
+/* Network emulator */
+
+enum {
+       TCA_NETEM_UNSPEC,
+       TCA_NETEM_CORR,
+       TCA_NETEM_DELAY_DIST,
+       TCA_NETEM_REORDER,
+       TCA_NETEM_CORRUPT,
+       TCA_NETEM_LOSS,
+       TCA_NETEM_RATE,
+       TCA_NETEM_ECN,
+       TCA_NETEM_RATE64,
+       TCA_NETEM_PAD,
+       TCA_NETEM_LATENCY64,
+       TCA_NETEM_JITTER64,
+       TCA_NETEM_SLOT,
+       TCA_NETEM_SLOT_DIST,
+       __TCA_NETEM_MAX,
+};
+
+#define TCA_NETEM_MAX (__TCA_NETEM_MAX - 1)
+
+struct tc_netem_qopt {
+       __u32   latency;        /* added delay (us) */
+       __u32   limit;          /* fifo limit (packets) */
+       __u32   loss;           /* random packet loss (0=none ~0=100%) */
+       __u32   gap;            /* re-ordering gap (0 for none) */
+       __u32   duplicate;      /* random packet dup  (0=none ~0=100%) */
+       __u32   jitter;         /* random jitter in latency (us) */
+};
+
+struct tc_netem_corr {
+       __u32   delay_corr;     /* delay correlation */
+       __u32   loss_corr;      /* packet loss correlation */
+       __u32   dup_corr;       /* duplicate correlation  */
+};
+
+struct tc_netem_reorder {
+       __u32   probability;
+       __u32   correlation;
+};
+
+struct tc_netem_corrupt {
+       __u32   probability;
+       __u32   correlation;
+};
+
+struct tc_netem_rate {
+       __u32   rate;   /* byte/s */
+       __s32   packet_overhead;
+       __u32   cell_size;
+       __s32   cell_overhead;
+};
+
+struct tc_netem_slot {
+       __s64   min_delay; /* nsec */
+       __s64   max_delay;
+       __s32   max_packets;
+       __s32   max_bytes;
+       __s64   dist_delay; /* nsec */
+       __s64   dist_jitter; /* nsec */
+};
+
+enum {
+       NETEM_LOSS_UNSPEC,
+       NETEM_LOSS_GI,          /* General Intuitive - 4 state model */
+       NETEM_LOSS_GE,          /* Gilbert Elliot models */
+       __NETEM_LOSS_MAX
+};
+#define NETEM_LOSS_MAX (__NETEM_LOSS_MAX - 1)
+
+/* State transition probabilities for 4 state model */
+struct tc_netem_gimodel {
+       __u32   p13;
+       __u32   p31;
+       __u32   p32;
+       __u32   p14;
+       __u32   p23;
+};
+
+/* Gilbert-Elliot models */
+struct tc_netem_gemodel {
+       __u32 p;
+       __u32 r;
+       __u32 h;
+       __u32 k1;
+};
+
+#define NETEM_DIST_SCALE       8192
+#define NETEM_DIST_MAX         16384
+
+/* DRR */
+
+enum {
+       TCA_DRR_UNSPEC,
+       TCA_DRR_QUANTUM,
+       __TCA_DRR_MAX
+};
+
+#define TCA_DRR_MAX    (__TCA_DRR_MAX - 1)
+
+struct tc_drr_stats {
+       __u32   deficit;
+};
+
+/* MQPRIO */
+#define TC_QOPT_BITMASK 15
+#define TC_QOPT_MAX_QUEUE 16
+
+enum {
+       TC_MQPRIO_HW_OFFLOAD_NONE,      /* no offload requested */
+       TC_MQPRIO_HW_OFFLOAD_TCS,       /* offload TCs, no queue counts */
+       __TC_MQPRIO_HW_OFFLOAD_MAX
+};
+
+#define TC_MQPRIO_HW_OFFLOAD_MAX (__TC_MQPRIO_HW_OFFLOAD_MAX - 1)
+
+enum {
+       TC_MQPRIO_MODE_DCB,
+       TC_MQPRIO_MODE_CHANNEL,
+       __TC_MQPRIO_MODE_MAX
+};
+
+#define __TC_MQPRIO_MODE_MAX (__TC_MQPRIO_MODE_MAX - 1)
+
+enum {
+       TC_MQPRIO_SHAPER_DCB,
+       TC_MQPRIO_SHAPER_BW_RATE,       /* Add new shapers below */
+       __TC_MQPRIO_SHAPER_MAX
+};
+
+#define __TC_MQPRIO_SHAPER_MAX (__TC_MQPRIO_SHAPER_MAX - 1)
+
+struct tc_mqprio_qopt {
+       __u8    num_tc;
+       __u8    prio_tc_map[TC_QOPT_BITMASK + 1];
+       __u8    hw;
+       __u16   count[TC_QOPT_MAX_QUEUE];
+       __u16   offset[TC_QOPT_MAX_QUEUE];
+};
+
+#define TC_MQPRIO_F_MODE               0x1
+#define TC_MQPRIO_F_SHAPER             0x2
+#define TC_MQPRIO_F_MIN_RATE           0x4
+#define TC_MQPRIO_F_MAX_RATE           0x8
+
+enum {
+       TCA_MQPRIO_UNSPEC,
+       TCA_MQPRIO_MODE,
+       TCA_MQPRIO_SHAPER,
+       TCA_MQPRIO_MIN_RATE64,
+       TCA_MQPRIO_MAX_RATE64,
+       __TCA_MQPRIO_MAX,
+};
+
+#define TCA_MQPRIO_MAX (__TCA_MQPRIO_MAX - 1)
+
+/* SFB */
+
+enum {
+       TCA_SFB_UNSPEC,
+       TCA_SFB_PARMS,
+       __TCA_SFB_MAX,
+};
+
+#define TCA_SFB_MAX (__TCA_SFB_MAX - 1)
+
+/*
+ * Note: increment, decrement are Q0.16 fixed-point values.
+ */
+struct tc_sfb_qopt {
+       __u32 rehash_interval;  /* delay between hash move, in ms */
+       __u32 warmup_time;      /* double buffering warmup time in ms (warmup_time < rehash_interval) */
+       __u32 max;              /* max len of qlen_min */
+       __u32 bin_size;         /* maximum queue length per bin */
+       __u32 increment;        /* probability increment, (d1 in Blue) */
+       __u32 decrement;        /* probability decrement, (d2 in Blue) */
+       __u32 limit;            /* max SFB queue length */
+       __u32 penalty_rate;     /* inelastic flows are rate limited to 'rate' pps */
+       __u32 penalty_burst;
+};
+
+struct tc_sfb_xstats {
+       __u32 earlydrop;
+       __u32 penaltydrop;
+       __u32 bucketdrop;
+       __u32 queuedrop;
+       __u32 childdrop; /* drops in child qdisc */
+       __u32 marked;
+       __u32 maxqlen;
+       __u32 maxprob;
+       __u32 avgprob;
+};
+
+#define SFB_MAX_PROB 0xFFFF
+
+/* QFQ */
+enum {
+       TCA_QFQ_UNSPEC,
+       TCA_QFQ_WEIGHT,
+       TCA_QFQ_LMAX,
+       __TCA_QFQ_MAX
+};
+
+#define TCA_QFQ_MAX    (__TCA_QFQ_MAX - 1)
+
+struct tc_qfq_stats {
+       __u32 weight;
+       __u32 lmax;
+};
+
+/* CODEL */
+
+enum {
+       TCA_CODEL_UNSPEC,
+       TCA_CODEL_TARGET,
+       TCA_CODEL_LIMIT,
+       TCA_CODEL_INTERVAL,
+       TCA_CODEL_ECN,
+       TCA_CODEL_CE_THRESHOLD,
+       __TCA_CODEL_MAX
+};
+
+#define TCA_CODEL_MAX  (__TCA_CODEL_MAX - 1)
+
+struct tc_codel_xstats {
+       __u32   maxpacket; /* largest packet we've seen so far */
+       __u32   count;     /* how many drops we've done since the last time we
+                           * entered dropping state
+                           */
+       __u32   lastcount; /* count at entry to dropping state */
+       __u32   ldelay;    /* in-queue delay seen by most recently dequeued packet */
+       __s32   drop_next; /* time to drop next packet */
+       __u32   drop_overlimit; /* number of time max qdisc packet limit was hit */
+       __u32   ecn_mark;  /* number of packets we ECN marked instead of dropped */
+       __u32   dropping;  /* are we in dropping state ? */
+       __u32   ce_mark;   /* number of CE marked packets because of ce_threshold */
+};
+
+/* FQ_CODEL */
+
+enum {
+       TCA_FQ_CODEL_UNSPEC,
+       TCA_FQ_CODEL_TARGET,
+       TCA_FQ_CODEL_LIMIT,
+       TCA_FQ_CODEL_INTERVAL,
+       TCA_FQ_CODEL_ECN,
+       TCA_FQ_CODEL_FLOWS,
+       TCA_FQ_CODEL_QUANTUM,
+       TCA_FQ_CODEL_CE_THRESHOLD,
+       TCA_FQ_CODEL_DROP_BATCH_SIZE,
+       TCA_FQ_CODEL_MEMORY_LIMIT,
+       __TCA_FQ_CODEL_MAX
+};
+
+#define TCA_FQ_CODEL_MAX       (__TCA_FQ_CODEL_MAX - 1)
+
+enum {
+       TCA_FQ_CODEL_XSTATS_QDISC,
+       TCA_FQ_CODEL_XSTATS_CLASS,
+};
+
+struct tc_fq_codel_qd_stats {
+       __u32   maxpacket;      /* largest packet we've seen so far */
+       __u32   drop_overlimit; /* number of time max qdisc
+                                * packet limit was hit
+                                */
+       __u32   ecn_mark;       /* number of packets we ECN marked
+                                * instead of being dropped
+                                */
+       __u32   new_flow_count; /* number of time packets
+                                * created a 'new flow'
+                                */
+       __u32   new_flows_len;  /* count of flows in new list */
+       __u32   old_flows_len;  /* count of flows in old list */
+       __u32   ce_mark;        /* packets above ce_threshold */
+       __u32   memory_usage;   /* in bytes */
+       __u32   drop_overmemory;
+};
+
+struct tc_fq_codel_cl_stats {
+       __s32   deficit;
+       __u32   ldelay;         /* in-queue delay seen by most recently
+                                * dequeued packet
+                                */
+       __u32   count;
+       __u32   lastcount;
+       __u32   dropping;
+       __s32   drop_next;
+};
+
+struct tc_fq_codel_xstats {
+       __u32   type;
+       union {
+               struct tc_fq_codel_qd_stats qdisc_stats;
+               struct tc_fq_codel_cl_stats class_stats;
+       };
+};
+
+/* FQ */
+
+enum {
+       TCA_FQ_UNSPEC,
+
+       TCA_FQ_PLIMIT,          /* limit of total number of packets in queue */
+
+       TCA_FQ_FLOW_PLIMIT,     /* limit of packets per flow */
+
+       TCA_FQ_QUANTUM,         /* RR quantum */
+
+       TCA_FQ_INITIAL_QUANTUM,         /* RR quantum for new flow */
+
+       TCA_FQ_RATE_ENABLE,     /* enable/disable rate limiting */
+
+       TCA_FQ_FLOW_DEFAULT_RATE,/* obsolete, do not use */
+
+       TCA_FQ_FLOW_MAX_RATE,   /* per flow max rate */
+
+       TCA_FQ_BUCKETS_LOG,     /* log2(number of buckets) */
+
+       TCA_FQ_FLOW_REFILL_DELAY,       /* flow credit refill delay in usec */
+
+       TCA_FQ_ORPHAN_MASK,     /* mask applied to orphaned skb hashes */
+
+       TCA_FQ_LOW_RATE_THRESHOLD, /* per packet delay under this rate */
+
+       TCA_FQ_CE_THRESHOLD,    /* DCTCP-like CE-marking threshold */
+
+       __TCA_FQ_MAX
+};
+
+#define TCA_FQ_MAX     (__TCA_FQ_MAX - 1)
+
+struct tc_fq_qd_stats {
+       __u64   gc_flows;
+       __u64   highprio_packets;
+       __u64   tcp_retrans;
+       __u64   throttled;
+       __u64   flows_plimit;
+       __u64   pkts_too_long;
+       __u64   allocation_errors;
+       __s64   time_next_delayed_flow;
+       __u32   flows;
+       __u32   inactive_flows;
+       __u32   throttled_flows;
+       __u32   unthrottle_latency_ns;
+       __u64   ce_mark;                /* packets above ce_threshold */
+};
+
+/* Heavy-Hitter Filter */
+
+enum {
+       TCA_HHF_UNSPEC,
+       TCA_HHF_BACKLOG_LIMIT,
+       TCA_HHF_QUANTUM,
+       TCA_HHF_HH_FLOWS_LIMIT,
+       TCA_HHF_RESET_TIMEOUT,
+       TCA_HHF_ADMIT_BYTES,
+       TCA_HHF_EVICT_TIMEOUT,
+       TCA_HHF_NON_HH_WEIGHT,
+       __TCA_HHF_MAX
+};
+
+#define TCA_HHF_MAX    (__TCA_HHF_MAX - 1)
+
+struct tc_hhf_xstats {
+       __u32   drop_overlimit; /* number of times max qdisc packet limit
+                                * was hit
+                                */
+       __u32   hh_overlimit;   /* number of times max heavy-hitters was hit */
+       __u32   hh_tot_count;   /* number of captured heavy-hitters so far */
+       __u32   hh_cur_count;   /* number of current heavy-hitters */
+};
+
+/* PIE */
+enum {
+       TCA_PIE_UNSPEC,
+       TCA_PIE_TARGET,
+       TCA_PIE_LIMIT,
+       TCA_PIE_TUPDATE,
+       TCA_PIE_ALPHA,
+       TCA_PIE_BETA,
+       TCA_PIE_ECN,
+       TCA_PIE_BYTEMODE,
+       __TCA_PIE_MAX
+};
+#define TCA_PIE_MAX   (__TCA_PIE_MAX - 1)
+
+struct tc_pie_xstats {
+       __u32 prob;             /* current probability */
+       __u32 delay;            /* current delay in ms */
+       __u32 avg_dq_rate;      /* current average dq_rate in bits/pie_time */
+       __u32 packets_in;       /* total number of packets enqueued */
+       __u32 dropped;          /* packets dropped due to pie_action */
+       __u32 overlimit;        /* dropped due to lack of space in queue */
+       __u32 maxq;             /* maximum queue size */
+       __u32 ecn_mark;         /* packets marked with ecn*/
+};
+
+/* CBS */
+struct tc_cbs_qopt {
+       __u8 offload;
+       __u8 _pad[3];
+       __s32 hicredit;
+       __s32 locredit;
+       __s32 idleslope;
+       __s32 sendslope;
+};
+
+enum {
+       TCA_CBS_UNSPEC,
+       TCA_CBS_PARMS,
+       __TCA_CBS_MAX,
+};
+
+#define TCA_CBS_MAX (__TCA_CBS_MAX - 1)
+
+
+/* ETF */
+struct tc_etf_qopt {
+       __s32 delta;
+       __s32 clockid;
+       __u32 flags;
+#define TC_ETF_DEADLINE_MODE_ON        BIT(0)
+#define TC_ETF_OFFLOAD_ON      BIT(1)
+};
+
+enum {
+       TCA_ETF_UNSPEC,
+       TCA_ETF_PARMS,
+       __TCA_ETF_MAX,
+};
+
+#define TCA_ETF_MAX (__TCA_ETF_MAX - 1)
+
+
+/* CAKE */
+enum {
+       TCA_CAKE_UNSPEC,
+       TCA_CAKE_PAD,
+       TCA_CAKE_BASE_RATE64,
+       TCA_CAKE_DIFFSERV_MODE,
+       TCA_CAKE_ATM,
+       TCA_CAKE_FLOW_MODE,
+       TCA_CAKE_OVERHEAD,
+       TCA_CAKE_RTT,
+       TCA_CAKE_TARGET,
+       TCA_CAKE_AUTORATE,
+       TCA_CAKE_MEMORY,
+       TCA_CAKE_NAT,
+       TCA_CAKE_RAW,
+       TCA_CAKE_WASH,
+       TCA_CAKE_MPU,
+       TCA_CAKE_INGRESS,
+       TCA_CAKE_ACK_FILTER,
+       TCA_CAKE_SPLIT_GSO,
+       __TCA_CAKE_MAX
+};
+#define TCA_CAKE_MAX   (__TCA_CAKE_MAX - 1)
+
+enum {
+       __TCA_CAKE_STATS_INVALID,
+       TCA_CAKE_STATS_PAD,
+       TCA_CAKE_STATS_CAPACITY_ESTIMATE64,
+       TCA_CAKE_STATS_MEMORY_LIMIT,
+       TCA_CAKE_STATS_MEMORY_USED,
+       TCA_CAKE_STATS_AVG_NETOFF,
+       TCA_CAKE_STATS_MIN_NETLEN,
+       TCA_CAKE_STATS_MAX_NETLEN,
+       TCA_CAKE_STATS_MIN_ADJLEN,
+       TCA_CAKE_STATS_MAX_ADJLEN,
+       TCA_CAKE_STATS_TIN_STATS,
+       TCA_CAKE_STATS_DEFICIT,
+       TCA_CAKE_STATS_COBALT_COUNT,
+       TCA_CAKE_STATS_DROPPING,
+       TCA_CAKE_STATS_DROP_NEXT_US,
+       TCA_CAKE_STATS_P_DROP,
+       TCA_CAKE_STATS_BLUE_TIMER_US,
+       __TCA_CAKE_STATS_MAX
+};
+#define TCA_CAKE_STATS_MAX (__TCA_CAKE_STATS_MAX - 1)
+
+enum {
+       __TCA_CAKE_TIN_STATS_INVALID,
+       TCA_CAKE_TIN_STATS_PAD,
+       TCA_CAKE_TIN_STATS_SENT_PACKETS,
+       TCA_CAKE_TIN_STATS_SENT_BYTES64,
+       TCA_CAKE_TIN_STATS_DROPPED_PACKETS,
+       TCA_CAKE_TIN_STATS_DROPPED_BYTES64,
+       TCA_CAKE_TIN_STATS_ACKS_DROPPED_PACKETS,
+       TCA_CAKE_TIN_STATS_ACKS_DROPPED_BYTES64,
+       TCA_CAKE_TIN_STATS_ECN_MARKED_PACKETS,
+       TCA_CAKE_TIN_STATS_ECN_MARKED_BYTES64,
+       TCA_CAKE_TIN_STATS_BACKLOG_PACKETS,
+       TCA_CAKE_TIN_STATS_BACKLOG_BYTES,
+       TCA_CAKE_TIN_STATS_THRESHOLD_RATE64,
+       TCA_CAKE_TIN_STATS_TARGET_US,
+       TCA_CAKE_TIN_STATS_INTERVAL_US,
+       TCA_CAKE_TIN_STATS_WAY_INDIRECT_HITS,
+       TCA_CAKE_TIN_STATS_WAY_MISSES,
+       TCA_CAKE_TIN_STATS_WAY_COLLISIONS,
+       TCA_CAKE_TIN_STATS_PEAK_DELAY_US,
+       TCA_CAKE_TIN_STATS_AVG_DELAY_US,
+       TCA_CAKE_TIN_STATS_BASE_DELAY_US,
+       TCA_CAKE_TIN_STATS_SPARSE_FLOWS,
+       TCA_CAKE_TIN_STATS_BULK_FLOWS,
+       TCA_CAKE_TIN_STATS_UNRESPONSIVE_FLOWS,
+       TCA_CAKE_TIN_STATS_MAX_SKBLEN,
+       TCA_CAKE_TIN_STATS_FLOW_QUANTUM,
+       __TCA_CAKE_TIN_STATS_MAX
+};
+#define TCA_CAKE_TIN_STATS_MAX (__TCA_CAKE_TIN_STATS_MAX - 1)
+#define TC_CAKE_MAX_TINS (8)
+
+enum {
+       CAKE_FLOW_NONE = 0,
+       CAKE_FLOW_SRC_IP,
+       CAKE_FLOW_DST_IP,
+       CAKE_FLOW_HOSTS,    /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_DST_IP */
+       CAKE_FLOW_FLOWS,
+       CAKE_FLOW_DUAL_SRC, /* = CAKE_FLOW_SRC_IP | CAKE_FLOW_FLOWS */
+       CAKE_FLOW_DUAL_DST, /* = CAKE_FLOW_DST_IP | CAKE_FLOW_FLOWS */
+       CAKE_FLOW_TRIPLE,   /* = CAKE_FLOW_HOSTS  | CAKE_FLOW_FLOWS */
+       CAKE_FLOW_MAX,
+};
+
+enum {
+       CAKE_DIFFSERV_DIFFSERV3 = 0,
+       CAKE_DIFFSERV_DIFFSERV4,
+       CAKE_DIFFSERV_DIFFSERV8,
+       CAKE_DIFFSERV_BESTEFFORT,
+       CAKE_DIFFSERV_PRECEDENCE,
+       CAKE_DIFFSERV_MAX
+};
+
+enum {
+       CAKE_ACK_NONE = 0,
+       CAKE_ACK_FILTER,
+       CAKE_ACK_AGGRESSIVE,
+       CAKE_ACK_MAX
+};
+
+enum {
+       CAKE_ATM_NONE = 0,
+       CAKE_ATM_ATM,
+       CAKE_ATM_PTM,
+       CAKE_ATM_MAX
+};
+
+
+/* TAPRIO */
+enum {
+       TC_TAPRIO_CMD_SET_GATES = 0x00,
+       TC_TAPRIO_CMD_SET_AND_HOLD = 0x01,
+       TC_TAPRIO_CMD_SET_AND_RELEASE = 0x02,
+};
+
+enum {
+       TCA_TAPRIO_SCHED_ENTRY_UNSPEC,
+       TCA_TAPRIO_SCHED_ENTRY_INDEX, /* u32 */
+       TCA_TAPRIO_SCHED_ENTRY_CMD, /* u8 */
+       TCA_TAPRIO_SCHED_ENTRY_GATE_MASK, /* u32 */
+       TCA_TAPRIO_SCHED_ENTRY_INTERVAL, /* u32 */
+       __TCA_TAPRIO_SCHED_ENTRY_MAX,
+};
+#define TCA_TAPRIO_SCHED_ENTRY_MAX (__TCA_TAPRIO_SCHED_ENTRY_MAX - 1)
+
+/* The format for schedule entry list is:
+ * [TCA_TAPRIO_SCHED_ENTRY_LIST]
+ *   [TCA_TAPRIO_SCHED_ENTRY]
+ *     [TCA_TAPRIO_SCHED_ENTRY_CMD]
+ *     [TCA_TAPRIO_SCHED_ENTRY_GATES]
+ *     [TCA_TAPRIO_SCHED_ENTRY_INTERVAL]
+ */
+enum {
+       TCA_TAPRIO_SCHED_UNSPEC,
+       TCA_TAPRIO_SCHED_ENTRY,
+       __TCA_TAPRIO_SCHED_MAX,
+};
+
+#define TCA_TAPRIO_SCHED_MAX (__TCA_TAPRIO_SCHED_MAX - 1)
+
+enum {
+       TCA_TAPRIO_ATTR_UNSPEC,
+       TCA_TAPRIO_ATTR_PRIOMAP, /* struct tc_mqprio_qopt */
+       TCA_TAPRIO_ATTR_SCHED_ENTRY_LIST, /* nested of entry */
+       TCA_TAPRIO_ATTR_SCHED_BASE_TIME, /* s64 */
+       TCA_TAPRIO_ATTR_SCHED_SINGLE_ENTRY, /* single entry */
+       TCA_TAPRIO_ATTR_SCHED_CLOCKID, /* s32 */
+       TCA_TAPRIO_PAD,
+       __TCA_TAPRIO_ATTR_MAX,
+};
+
+#define TCA_TAPRIO_ATTR_MAX (__TCA_TAPRIO_ATTR_MAX - 1)
+
+#endif
index b17201e..b4875a9 100644 (file)
@@ -220,4 +220,12 @@ struct prctl_mm_map {
 # define PR_SPEC_DISABLE               (1UL << 2)
 # define PR_SPEC_FORCE_DISABLE         (1UL << 3)
 
+/* Reset arm64 pointer authentication keys */
+#define PR_PAC_RESET_KEYS              54
+# define PR_PAC_APIAKEY                        (1UL << 0)
+# define PR_PAC_APIBKEY                        (1UL << 1)
+# define PR_PAC_APDAKEY                        (1UL << 2)
+# define PR_PAC_APDBKEY                        (1UL << 3)
+# define PR_PAC_APGAKEY                        (1UL << 4)
+
 #endif /* _LINUX_PRCTL_H */
index 84c3de8..40d028e 100644 (file)
  * device configuration.
  */
 
+#include <linux/vhost_types.h>
 #include <linux/types.h>
-#include <linux/compiler.h>
 #include <linux/ioctl.h>
-#include <linux/virtio_config.h>
-#include <linux/virtio_ring.h>
-
-struct vhost_vring_state {
-       unsigned int index;
-       unsigned int num;
-};
-
-struct vhost_vring_file {
-       unsigned int index;
-       int fd; /* Pass -1 to unbind from file. */
-
-};
-
-struct vhost_vring_addr {
-       unsigned int index;
-       /* Option flags. */
-       unsigned int flags;
-       /* Flag values: */
-       /* Whether log address is valid. If set enables logging. */
-#define VHOST_VRING_F_LOG 0
-
-       /* Start of array of descriptors (virtually contiguous) */
-       __u64 desc_user_addr;
-       /* Used structure address. Must be 32 bit aligned */
-       __u64 used_user_addr;
-       /* Available structure address. Must be 16 bit aligned */
-       __u64 avail_user_addr;
-       /* Logging support. */
-       /* Log writes to used structure, at offset calculated from specified
-        * address. Address must be 32 bit aligned. */
-       __u64 log_guest_addr;
-};
-
-/* no alignment requirement */
-struct vhost_iotlb_msg {
-       __u64 iova;
-       __u64 size;
-       __u64 uaddr;
-#define VHOST_ACCESS_RO      0x1
-#define VHOST_ACCESS_WO      0x2
-#define VHOST_ACCESS_RW      0x3
-       __u8 perm;
-#define VHOST_IOTLB_MISS           1
-#define VHOST_IOTLB_UPDATE         2
-#define VHOST_IOTLB_INVALIDATE     3
-#define VHOST_IOTLB_ACCESS_FAIL    4
-       __u8 type;
-};
-
-#define VHOST_IOTLB_MSG 0x1
-#define VHOST_IOTLB_MSG_V2 0x2
-
-struct vhost_msg {
-       int type;
-       union {
-               struct vhost_iotlb_msg iotlb;
-               __u8 padding[64];
-       };
-};
-
-struct vhost_msg_v2 {
-       __u32 type;
-       __u32 reserved;
-       union {
-               struct vhost_iotlb_msg iotlb;
-               __u8 padding[64];
-       };
-};
-
-struct vhost_memory_region {
-       __u64 guest_phys_addr;
-       __u64 memory_size; /* bytes */
-       __u64 userspace_addr;
-       __u64 flags_padding; /* No flags are currently specified. */
-};
-
-/* All region addresses and sizes must be 4K aligned. */
-#define VHOST_PAGE_SIZE 0x1000
-
-struct vhost_memory {
-       __u32 nregions;
-       __u32 padding;
-       struct vhost_memory_region regions[0];
-};
 
 /* ioctls */
 
@@ -186,31 +101,7 @@ struct vhost_memory {
  * device.  This can be used to stop the ring (e.g. for migration). */
 #define VHOST_NET_SET_BACKEND _IOW(VHOST_VIRTIO, 0x30, struct vhost_vring_file)
 
-/* Feature bits */
-/* Log all write descriptors. Can be changed while device is active. */
-#define VHOST_F_LOG_ALL 26
-/* vhost-net should add virtio_net_hdr for RX, and strip for TX packets. */
-#define VHOST_NET_F_VIRTIO_NET_HDR 27
-
-/* VHOST_SCSI specific definitions */
-
-/*
- * Used by QEMU userspace to ensure a consistent vhost-scsi ABI.
- *
- * ABI Rev 0: July 2012 version starting point for v3.6-rc merge candidate +
- *            RFC-v2 vhost-scsi userspace.  Add GET_ABI_VERSION ioctl usage
- * ABI Rev 1: January 2013. Ignore vhost_tpgt filed in struct vhost_scsi_target.
- *            All the targets under vhost_wwpn can be seen and used by guset.
- */
-
-#define VHOST_SCSI_ABI_VERSION 1
-
-struct vhost_scsi_target {
-       int abi_version;
-       char vhost_wwpn[224]; /* TRANSPORT_IQN_LEN */
-       unsigned short vhost_tpgt;
-       unsigned short reserved;
-};
+/* VHOST_SCSI specific defines */
 
 #define VHOST_SCSI_SET_ENDPOINT _IOW(VHOST_VIRTIO, 0x40, struct vhost_scsi_target)
 #define VHOST_SCSI_CLEAR_ENDPOINT _IOW(VHOST_VIRTIO, 0x41, struct vhost_scsi_target)
index f81e549..4db7475 100644 (file)
@@ -1,2 +1,3 @@
 libbpf_version.h
 FEATURE-DUMP.libbpf
+test_libbpf
index 056f383..607aae4 100644 (file)
@@ -132,6 +132,20 @@ For example, if current state of ``libbpf.map`` is:
 Format of version script and ways to handle ABI changes, including
 incompatible ones, described in details in [1].
 
+Stand-alone build
+=================
+
+Under https://github.com/libbpf/libbpf there is a (semi-)automated
+mirror of the mainline's version of libbpf for a stand-alone build.
+
+However, all changes to libbpf's code base must be upstreamed through
+the mainline kernel tree.
+
+License
+=======
+
+libbpf is dual-licensed under LGPL 2.1 and BSD 2-Clause.
+
 Links
 =====
 
index 3caaa34..88cbd11 100644 (file)
@@ -65,6 +65,17 @@ static inline int sys_bpf(enum bpf_cmd cmd, union bpf_attr *attr,
        return syscall(__NR_bpf, cmd, attr, size);
 }
 
+static inline int sys_bpf_prog_load(union bpf_attr *attr, unsigned int size)
+{
+       int fd;
+
+       do {
+               fd = sys_bpf(BPF_PROG_LOAD, attr, size);
+       } while (fd < 0 && errno == EAGAIN);
+
+       return fd;
+}
+
 int bpf_create_map_xattr(const struct bpf_create_map_attr *create_attr)
 {
        __u32 name_len = create_attr->name ? strlen(create_attr->name) : 0;
@@ -232,7 +243,7 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
        memcpy(attr.prog_name, load_attr->name,
               min(name_len, BPF_OBJ_NAME_LEN - 1));
 
-       fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+       fd = sys_bpf_prog_load(&attr, sizeof(attr));
        if (fd >= 0)
                return fd;
 
@@ -269,7 +280,7 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
                        break;
                }
 
-               fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+               fd = sys_bpf_prog_load(&attr, sizeof(attr));
 
                if (fd >= 0)
                        goto done;
@@ -283,7 +294,7 @@ int bpf_load_program_xattr(const struct bpf_load_program_attr *load_attr,
        attr.log_size = log_buf_sz;
        attr.log_level = 1;
        log_buf[0] = 0;
-       fd = sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+       fd = sys_bpf_prog_load(&attr, sizeof(attr));
 done:
        free(finfo);
        free(linfo);
@@ -328,7 +339,7 @@ int bpf_verify_program(enum bpf_prog_type type, const struct bpf_insn *insns,
        attr.kern_version = kern_version;
        attr.prog_flags = prog_flags;
 
-       return sys_bpf(BPF_PROG_LOAD, &attr, sizeof(attr));
+       return sys_bpf_prog_load(&attr, sizeof(attr));
 }
 
 int bpf_map_update_elem(int fd, const void *key, const void *value,
index 8b31c0e..d463761 100644 (file)
@@ -194,13 +194,13 @@ void tep_set_page_size(struct tep_handle *pevent, int _page_size)
 }
 
 /**
- * tep_is_file_bigendian - get if the file is in big endian order
+ * tep_file_bigendian - get if the file is in big endian order
  * @pevent: a handle to the tep_handle
  *
  * This returns if the file is in big endian order
  * If @pevent is NULL, 0 is returned.
  */
-int tep_is_file_bigendian(struct tep_handle *pevent)
+int tep_file_bigendian(struct tep_handle *pevent)
 {
        if(pevent)
                return pevent->file_bigendian;
index 9a092dd..35833ee 100644 (file)
@@ -7,7 +7,7 @@
 #ifndef _PARSE_EVENTS_INT_H
 #define _PARSE_EVENTS_INT_H
 
-struct cmdline;
+struct tep_cmdline;
 struct cmdline_list;
 struct func_map;
 struct func_list;
@@ -36,7 +36,7 @@ struct tep_handle {
        int long_size;
        int page_size;
 
-       struct cmdline *cmdlines;
+       struct tep_cmdline *cmdlines;
        struct cmdline_list *cmdlist;
        int cmdline_count;
 
index 69a96e3..abd4fa5 100644 (file)
@@ -124,15 +124,15 @@ struct tep_print_arg *alloc_arg(void)
        return calloc(1, sizeof(struct tep_print_arg));
 }
 
-struct cmdline {
+struct tep_cmdline {
        char *comm;
        int pid;
 };
 
 static int cmdline_cmp(const void *a, const void *b)
 {
-       const struct cmdline *ca = a;
-       const struct cmdline *cb = b;
+       const struct tep_cmdline *ca = a;
+       const struct tep_cmdline *cb = b;
 
        if (ca->pid < cb->pid)
                return -1;
@@ -152,7 +152,7 @@ static int cmdline_init(struct tep_handle *pevent)
 {
        struct cmdline_list *cmdlist = pevent->cmdlist;
        struct cmdline_list *item;
-       struct cmdline *cmdlines;
+       struct tep_cmdline *cmdlines;
        int i;
 
        cmdlines = malloc(sizeof(*cmdlines) * pevent->cmdline_count);
@@ -179,8 +179,8 @@ static int cmdline_init(struct tep_handle *pevent)
 
 static const char *find_cmdline(struct tep_handle *pevent, int pid)
 {
-       const struct cmdline *comm;
-       struct cmdline key;
+       const struct tep_cmdline *comm;
+       struct tep_cmdline key;
 
        if (!pid)
                return "<idle>";
@@ -208,8 +208,8 @@ static const char *find_cmdline(struct tep_handle *pevent, int pid)
  */
 int tep_pid_is_registered(struct tep_handle *pevent, int pid)
 {
-       const struct cmdline *comm;
-       struct cmdline key;
+       const struct tep_cmdline *comm;
+       struct tep_cmdline key;
 
        if (!pid)
                return 1;
@@ -232,11 +232,13 @@ int tep_pid_is_registered(struct tep_handle *pevent, int pid)
  * we must add this pid. This is much slower than when cmdlines
  * are added before the array is initialized.
  */
-static int add_new_comm(struct tep_handle *pevent, const char *comm, int pid)
+static int add_new_comm(struct tep_handle *pevent,
+                       const char *comm, int pid, bool override)
 {
-       struct cmdline *cmdlines = pevent->cmdlines;
-       const struct cmdline *cmdline;
-       struct cmdline key;
+       struct tep_cmdline *cmdlines = pevent->cmdlines;
+       struct tep_cmdline *cmdline;
+       struct tep_cmdline key;
+       char *new_comm;
 
        if (!pid)
                return 0;
@@ -247,8 +249,19 @@ static int add_new_comm(struct tep_handle *pevent, const char *comm, int pid)
        cmdline = bsearch(&key, pevent->cmdlines, pevent->cmdline_count,
                       sizeof(*pevent->cmdlines), cmdline_cmp);
        if (cmdline) {
-               errno = EEXIST;
-               return -1;
+               if (!override) {
+                       errno = EEXIST;
+                       return -1;
+               }
+               new_comm = strdup(comm);
+               if (!new_comm) {
+                       errno = ENOMEM;
+                       return -1;
+               }
+               free(cmdline->comm);
+               cmdline->comm = new_comm;
+
+               return 0;
        }
 
        cmdlines = realloc(cmdlines, sizeof(*cmdlines) * (pevent->cmdline_count + 1));
@@ -275,21 +288,13 @@ static int add_new_comm(struct tep_handle *pevent, const char *comm, int pid)
        return 0;
 }
 
-/**
- * tep_register_comm - register a pid / comm mapping
- * @pevent: handle for the pevent
- * @comm: the command line to register
- * @pid: the pid to map the command line to
- *
- * This adds a mapping to search for command line names with
- * a given pid. The comm is duplicated.
- */
-int tep_register_comm(struct tep_handle *pevent, const char *comm, int pid)
+static int _tep_register_comm(struct tep_handle *pevent,
+                             const char *comm, int pid, bool override)
 {
        struct cmdline_list *item;
 
        if (pevent->cmdlines)
-               return add_new_comm(pevent, comm, pid);
+               return add_new_comm(pevent, comm, pid, override);
 
        item = malloc(sizeof(*item));
        if (!item)
@@ -312,6 +317,40 @@ int tep_register_comm(struct tep_handle *pevent, const char *comm, int pid)
        return 0;
 }
 
+/**
+ * tep_register_comm - register a pid / comm mapping
+ * @pevent: handle for the pevent
+ * @comm: the command line to register
+ * @pid: the pid to map the command line to
+ *
+ * This adds a mapping to search for command line names with
+ * a given pid. The comm is duplicated. If a command with the same pid
+ * already exist, -1 is returned and errno is set to EEXIST
+ */
+int tep_register_comm(struct tep_handle *pevent, const char *comm, int pid)
+{
+       return _tep_register_comm(pevent, comm, pid, false);
+}
+
+/**
+ * tep_override_comm - register a pid / comm mapping
+ * @pevent: handle for the pevent
+ * @comm: the command line to register
+ * @pid: the pid to map the command line to
+ *
+ * This adds a mapping to search for command line names with
+ * a given pid. The comm is duplicated. If a command with the same pid
+ * already exist, the command string is udapted with the new one
+ */
+int tep_override_comm(struct tep_handle *pevent, const char *comm, int pid)
+{
+       if (!pevent->cmdlines && cmdline_init(pevent)) {
+               errno = ENOMEM;
+               return -1;
+       }
+       return _tep_register_comm(pevent, comm, pid, true);
+}
+
 int tep_register_trace_clock(struct tep_handle *pevent, const char *trace_clock)
 {
        pevent->trace_clock = strdup(trace_clock);
@@ -5226,18 +5265,6 @@ int tep_data_type(struct tep_handle *pevent, struct tep_record *rec)
        return trace_parse_common_type(pevent, rec->data);
 }
 
-/**
- * tep_data_event_from_type - find the event by a given type
- * @pevent: a handle to the pevent
- * @type: the type of the event.
- *
- * This returns the event form a given @type;
- */
-struct tep_event *tep_data_event_from_type(struct tep_handle *pevent, int type)
-{
-       return tep_find_event(pevent, type);
-}
-
 /**
  * tep_data_pid - parse the PID from record
  * @pevent: a handle to the pevent
@@ -5292,8 +5319,8 @@ const char *tep_data_comm_from_pid(struct tep_handle *pevent, int pid)
        return comm;
 }
 
-static struct cmdline *
-pid_from_cmdlist(struct tep_handle *pevent, const char *comm, struct cmdline *next)
+static struct tep_cmdline *
+pid_from_cmdlist(struct tep_handle *pevent, const char *comm, struct tep_cmdline *next)
 {
        struct cmdline_list *cmdlist = (struct cmdline_list *)next;
 
@@ -5305,7 +5332,7 @@ pid_from_cmdlist(struct tep_handle *pevent, const char *comm, struct cmdline *ne
        while (cmdlist && strcmp(cmdlist->comm, comm) != 0)
                cmdlist = cmdlist->next;
 
-       return (struct cmdline *)cmdlist;
+       return (struct tep_cmdline *)cmdlist;
 }
 
 /**
@@ -5321,10 +5348,10 @@ pid_from_cmdlist(struct tep_handle *pevent, const char *comm, struct cmdline *ne
  * next pid.
  * Also, it does a linear search, so it may be slow.
  */
-struct cmdline *tep_data_pid_from_comm(struct tep_handle *pevent, const char *comm,
-                                      struct cmdline *next)
+struct tep_cmdline *tep_data_pid_from_comm(struct tep_handle *pevent, const char *comm,
+                                          struct tep_cmdline *next)
 {
-       struct cmdline *cmdline;
+       struct tep_cmdline *cmdline;
 
        /*
         * If the cmdlines have not been converted yet, then use
@@ -5363,7 +5390,7 @@ struct cmdline *tep_data_pid_from_comm(struct tep_handle *pevent, const char *co
  * Returns the pid for a give cmdline. If @cmdline is NULL, then
  * -1 is returned.
  */
-int tep_cmdline_pid(struct tep_handle *pevent, struct cmdline *cmdline)
+int tep_cmdline_pid(struct tep_handle *pevent, struct tep_cmdline *cmdline)
 {
        struct cmdline_list *cmdlist = (struct cmdline_list *)cmdline;
 
@@ -6593,6 +6620,12 @@ static struct tep_event *search_event(struct tep_handle *pevent, int id,
  *
  * If @id is >= 0, then it is used to find the event.
  * else @sys_name and @event_name are used.
+ *
+ * Returns:
+ *  TEP_REGISTER_SUCCESS_OVERWRITE if an existing handler is overwritten
+ *  TEP_REGISTER_SUCCESS if a new handler is registered successfully
+ *  negative TEP_ERRNO_... in case of an error
+ *
  */
 int tep_register_event_handler(struct tep_handle *pevent, int id,
                               const char *sys_name, const char *event_name,
@@ -6610,7 +6643,7 @@ int tep_register_event_handler(struct tep_handle *pevent, int id,
 
        event->handler = func;
        event->context = context;
-       return 0;
+       return TEP_REGISTER_SUCCESS_OVERWRITE;
 
  not_found:
        /* Save for later use. */
@@ -6640,7 +6673,7 @@ int tep_register_event_handler(struct tep_handle *pevent, int id,
        pevent->handlers = handle;
        handle->context = context;
 
-       return -1;
+       return TEP_REGISTER_SUCCESS;
 }
 
 static int handle_matches(struct event_handler *handler, int id,
@@ -6723,8 +6756,10 @@ struct tep_handle *tep_alloc(void)
 {
        struct tep_handle *pevent = calloc(1, sizeof(*pevent));
 
-       if (pevent)
+       if (pevent) {
                pevent->ref_count = 1;
+               pevent->host_bigendian = tep_host_bigendian();
+       }
 
        return pevent;
 }
index 35d3708..aec48f2 100644 (file)
@@ -432,6 +432,7 @@ int tep_set_function_resolver(struct tep_handle *pevent,
                              tep_func_resolver_t *func, void *priv);
 void tep_reset_function_resolver(struct tep_handle *pevent);
 int tep_register_comm(struct tep_handle *pevent, const char *comm, int pid);
+int tep_override_comm(struct tep_handle *pevent, const char *comm, int pid);
 int tep_register_trace_clock(struct tep_handle *pevent, const char *trace_clock);
 int tep_register_function(struct tep_handle *pevent, char *name,
                          unsigned long long addr, char *mod);
@@ -484,6 +485,11 @@ int tep_print_func_field(struct trace_seq *s, const char *fmt,
                         struct tep_event *event, const char *name,
                         struct tep_record *record, int err);
 
+enum tep_reg_handler {
+       TEP_REGISTER_SUCCESS = 0,
+       TEP_REGISTER_SUCCESS_OVERWRITE,
+};
+
 int tep_register_event_handler(struct tep_handle *pevent, int id,
                               const char *sys_name, const char *event_name,
                               tep_event_handler_func func, void *context);
@@ -520,15 +526,14 @@ tep_find_event_by_record(struct tep_handle *pevent, struct tep_record *record);
 void tep_data_lat_fmt(struct tep_handle *pevent,
                      struct trace_seq *s, struct tep_record *record);
 int tep_data_type(struct tep_handle *pevent, struct tep_record *rec);
-struct tep_event *tep_data_event_from_type(struct tep_handle *pevent, int type);
 int tep_data_pid(struct tep_handle *pevent, struct tep_record *rec);
 int tep_data_preempt_count(struct tep_handle *pevent, struct tep_record *rec);
 int tep_data_flags(struct tep_handle *pevent, struct tep_record *rec);
 const char *tep_data_comm_from_pid(struct tep_handle *pevent, int pid);
-struct cmdline;
-struct cmdline *tep_data_pid_from_comm(struct tep_handle *pevent, const char *comm,
-                                      struct cmdline *next);
-int tep_cmdline_pid(struct tep_handle *pevent, struct cmdline *cmdline);
+struct tep_cmdline;
+struct tep_cmdline *tep_data_pid_from_comm(struct tep_handle *pevent, const char *comm,
+                                          struct tep_cmdline *next);
+int tep_cmdline_pid(struct tep_handle *pevent, struct tep_cmdline *cmdline);
 
 void tep_print_field(struct trace_seq *s, void *data,
                     struct tep_format_field *field);
@@ -553,7 +558,7 @@ int tep_get_long_size(struct tep_handle *pevent);
 void tep_set_long_size(struct tep_handle *pevent, int long_size);
 int tep_get_page_size(struct tep_handle *pevent);
 void tep_set_page_size(struct tep_handle *pevent, int _page_size);
-int tep_is_file_bigendian(struct tep_handle *pevent);
+int tep_file_bigendian(struct tep_handle *pevent);
 void tep_set_file_bigendian(struct tep_handle *pevent, enum tep_endian endian);
 int tep_is_host_bigendian(struct tep_handle *pevent);
 void tep_set_host_bigendian(struct tep_handle *pevent, enum tep_endian endian);
index 754050e..64b9c25 100644 (file)
@@ -389,7 +389,7 @@ static int kvm_mmu_print_role(struct trace_seq *s, struct tep_record *record,
         * We can only use the structure if file is of the same
         * endianness.
         */
-       if (tep_is_file_bigendian(event->pevent) ==
+       if (tep_file_bigendian(event->pevent) ==
            tep_is_host_bigendian(event->pevent)) {
 
                trace_seq_printf(s, "%u q%u%s %s%s %spae %snxe %swp%s%s%s",
index 8ff1d55..8d5ecd2 100644 (file)
@@ -100,7 +100,8 @@ static void expand_buffer(struct trace_seq *s)
  * @fmt: printf format string
  *
  * It returns 0 if the trace oversizes the buffer's free
- * space, 1 otherwise.
+ * space, the number of characters printed, or a negative
+ * value in case of an error.
  *
  * The tracer may use either sequence operations or its own
  * copy to user routines. To simplify formating of a trace
@@ -129,9 +130,10 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
                goto try_again;
        }
 
-       s->len += ret;
+       if (ret > 0)
+               s->len += ret;
 
-       return 1;
+       return ret;
 }
 
 /**
@@ -139,6 +141,10 @@ trace_seq_printf(struct trace_seq *s, const char *fmt, ...)
  * @s: trace sequence descriptor
  * @fmt: printf format string
  *
+ * It returns 0 if the trace oversizes the buffer's free
+ * space, the number of characters printed, or a negative
+ * value in case of an error.
+ * *
  * The tracer may use either sequence operations or its own
  * copy to user routines. To simplify formating of a trace
  * trace_seq_printf is used to store strings into a special
@@ -163,9 +169,10 @@ trace_seq_vprintf(struct trace_seq *s, const char *fmt, va_list args)
                goto try_again;
        }
 
-       s->len += ret;
+       if (ret > 0)
+               s->len += ret;
 
-       return len;
+       return ret;
 }
 
 /**
index 095aebd..e6150f2 100644 (file)
@@ -19,8 +19,11 @@ C2C stands for Cache To Cache.
 The perf c2c tool provides means for Shared Data C2C/HITM analysis. It allows
 you to track down the cacheline contentions.
 
-The tool is based on x86's load latency and precise store facility events
-provided by Intel CPUs. These events provide:
+On x86, the tool is based on load latency and precise store facility events
+provided by Intel CPUs. On PowerPC, the tool uses random instruction sampling
+with thresholding feature.
+
+These events provide:
   - memory address of the access
   - type of the access (load and store details)
   - latency (in cycles) of the load access
@@ -46,7 +49,7 @@ RECORD OPTIONS
 
 -l::
 --ldlat::
-       Configure mem-loads latency.
+       Configure mem-loads latency. (x86 only)
 
 -k::
 --all-kernel::
@@ -119,11 +122,16 @@ Following perf record options are configured by default:
   -W,-d,--phys-data,--sample-cpu
 
 Unless specified otherwise with '-e' option, following events are monitored by
-default:
+default on x86:
 
   cpu/mem-loads,ldlat=30/P
   cpu/mem-stores/P
 
+and following on PowerPC:
+
+  cpu/mem-loads/
+  cpu/mem-stores/
+
 User can pass any 'perf record' option behind '--' mark, like (to enable
 callchains and system wide monitoring):
 
index f8d2167..199ea0f 100644 (file)
@@ -82,7 +82,7 @@ RECORD OPTIONS
        Be more verbose (show counter open errors, etc)
 
 --ldlat <n>::
-       Specify desired latency for loads event.
+       Specify desired latency for loads event. (x86 only)
 
 In addition, for report all perf report options are valid, and for record
 all perf record options.
index ff29c33..0ee6795 100644 (file)
@@ -524,12 +524,14 @@ $(arch_errno_name_array): $(arch_errno_tbl)
 
 all: shell_compatibility_test $(ALL_PROGRAMS) $(LANG_BINDINGS) $(OTHER_PROGRAMS)
 
+# Create python binding output directory if not already present
+_dummy := $(shell [ -d '$(OUTPUT)python' ] || mkdir -p '$(OUTPUT)python')
+
 $(OUTPUT)python/perf.so: $(PYTHON_EXT_SRCS) $(PYTHON_EXT_DEPS) $(LIBTRACEEVENT_DYNAMIC_LIST)
        $(QUIET_GEN)LDSHARED="$(CC) -pthread -shared" \
         CFLAGS='$(CFLAGS)' LDFLAGS='$(LDFLAGS) $(LIBTRACEEVENT_DYNAMIC_LIST_LDFLAGS)' \
          $(PYTHON_WORD) util/setup.py \
          --quiet build_ext; \
-       mkdir -p $(OUTPUT)python && \
        cp $(PYTHON_EXTBUILD_LIB)perf*.so $(OUTPUT)python/
 
 please_set_SHELL_PATH_to_a_more_modern_shell:
@@ -660,12 +662,12 @@ $(OUTPUT)perf-%: %.o $(PERFLIBS)
        $(QUIET_LINK)$(CC) $(CFLAGS) -o $@ $(LDFLAGS) $(filter %.o,$^) $(LIBS)
 
 ifndef NO_PERF_READ_VDSO32
-$(OUTPUT)perf-read-vdso32: perf-read-vdso.c util/find-vdso-map.c
+$(OUTPUT)perf-read-vdso32: perf-read-vdso.c util/find-map.c
        $(QUIET_CC)$(CC) -m32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
 endif
 
 ifndef NO_PERF_READ_VDSOX32
-$(OUTPUT)perf-read-vdsox32: perf-read-vdso.c util/find-vdso-map.c
+$(OUTPUT)perf-read-vdsox32: perf-read-vdso.c util/find-map.c
        $(QUIET_CC)$(CC) -mx32 $(filter -static,$(LDFLAGS)) -Wall -Werror -o $@ perf-read-vdso.c
 endif
 
index 883c57f..d9ae273 100644 (file)
@@ -1,4 +1,5 @@
 libperf-y += regs_load.o
 libperf-y += dwarf-unwind.o
+libperf-y += vectors-page.o
 
 libperf-y += arch-tests.o
index 5b1543c..6848101 100644 (file)
@@ -10,6 +10,10 @@ struct test arch_tests[] = {
                .func = test__dwarf_unwind,
        },
 #endif
+       {
+               .desc = "Vectors page",
+               .func = test__vectors_page,
+       },
        {
                .func = NULL,
        },
diff --git a/tools/perf/arch/arm/tests/vectors-page.c b/tools/perf/arch/arm/tests/vectors-page.c
new file mode 100644 (file)
index 0000000..7ffdd79
--- /dev/null
@@ -0,0 +1,24 @@
+// SPDX-License-Identifier: GPL-2.0
+#include <stdio.h>
+#include <string.h>
+#include <linux/compiler.h>
+
+#include "debug.h"
+#include "tests/tests.h"
+#include "util/find-map.c"
+
+#define VECTORS__MAP_NAME "[vectors]"
+
+int test__vectors_page(struct test *test __maybe_unused,
+                      int subtest __maybe_unused)
+{
+       void *start, *end;
+
+       if (find_map(&start, &end, VECTORS__MAP_NAME)) {
+               pr_err("%s not found, is CONFIG_KUSER_HELPERS enabled?\n",
+                      VECTORS__MAP_NAME);
+               return TEST_FAIL;
+       }
+
+       return TEST_OK;
+}
index a111239..e58d00d 100644 (file)
@@ -14,18 +14,25 @@ PERF_HAVE_JITDUMP := 1
 out    := $(OUTPUT)arch/powerpc/include/generated/asm
 header32 := $(out)/syscalls_32.c
 header64 := $(out)/syscalls_64.c
-sysdef := $(srctree)/tools/arch/powerpc/include/uapi/asm/unistd.h
-sysprf := $(srctree)/tools/perf/arch/powerpc/entry/syscalls/
+syskrn := $(srctree)/arch/powerpc/kernel/syscalls/syscall.tbl
+sysprf := $(srctree)/tools/perf/arch/powerpc/entry/syscalls
+sysdef := $(sysprf)/syscall.tbl
 systbl := $(sysprf)/mksyscalltbl
 
 # Create output directory if not already present
 _dummy := $(shell [ -d '$(out)' ] || mkdir -p '$(out)')
 
 $(header64): $(sysdef) $(systbl)
-       $(Q)$(SHELL) '$(systbl)' '64' '$(CC)' $(sysdef) > $@
+       @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
+       (diff -B $(sysdef) $(syskrn) >/dev/null) \
+       || echo "Warning: Kernel ABI header at '$(sysdef)' differs from latest version at '$(syskrn)'" >&2 )) || true
+       $(Q)$(SHELL) '$(systbl)' '64' $(sysdef) > $@
 
 $(header32): $(sysdef) $(systbl)
-       $(Q)$(SHELL) '$(systbl)' '32' '$(CC)' $(sysdef) > $@
+       @(test -d ../../kernel -a -d ../../tools -a -d ../perf && ( \
+       (diff -B $(sysdef) $(syskrn) >/dev/null) \
+       || echo "Warning: Kernel ABI header at '$(sysdef)' differs from latest version at '$(syskrn)'" >&2 )) || true
+       $(Q)$(SHELL) '$(systbl)' '32' $(sysdef) > $@
 
 clean::
        $(call QUIET_CLEAN, powerpc) $(RM) $(header32) $(header64)
index ef52e1d..6c58060 100755 (executable)
@@ -9,10 +9,9 @@
 # Changed by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
 
 wordsize=$1
-gcc=$2
-input=$3
+SYSCALL_TBL=$2
 
-if ! test -r $input; then
+if ! test -r $SYSCALL_TBL; then
        echo "Could not read input file" >&2
        exit 1
 fi
@@ -20,18 +19,21 @@ fi
 create_table()
 {
        local wordsize=$1
-       local max_nr
+       local max_nr nr abi sc discard
+       max_nr=-1
+       nr=0
 
        echo "static const char *syscalltbl_powerpc_${wordsize}[] = {"
-       while read sc nr; do
-               printf '\t[%d] = "%s",\n' $nr $sc
-               max_nr=$nr
+       while read nr abi sc discard; do
+               if [ "$max_nr" -lt "$nr" ]; then
+                       printf '\t[%d] = "%s",\n' $nr $sc
+                       max_nr=$nr
+               fi
        done
        echo '};'
        echo "#define SYSCALLTBL_POWERPC_${wordsize}_MAX_ID $max_nr"
 }
 
-$gcc -m${wordsize} -E -dM -x c  $input        \
-       |sed -ne 's/^#define __NR_//p' \
-       |sort -t' ' -k2 -nu            \
+grep -E "^[[:digit:]]+[[:space:]]+(common|spu|nospu|${wordsize})" $SYSCALL_TBL \
+       |sort -k1 -n                                                           \
        |create_table ${wordsize}
diff --git a/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl b/tools/perf/arch/powerpc/entry/syscalls/syscall.tbl
new file mode 100644 (file)
index 0000000..db3bbb8
--- /dev/null
@@ -0,0 +1,427 @@
+# SPDX-License-Identifier: GPL-2.0 WITH Linux-syscall-note
+#
+# system call numbers and entry vectors for powerpc
+#
+# The format is:
+# <number> <abi> <name> <entry point> <compat entry point>
+#
+# The <abi> can be common, spu, nospu, 64, or 32 for this file.
+#
+0      nospu   restart_syscall                 sys_restart_syscall
+1      nospu   exit                            sys_exit
+2      nospu   fork                            ppc_fork
+3      common  read                            sys_read
+4      common  write                           sys_write
+5      common  open                            sys_open                        compat_sys_open
+6      common  close                           sys_close
+7      common  waitpid                         sys_waitpid
+8      common  creat                           sys_creat
+9      common  link                            sys_link
+10     common  unlink                          sys_unlink
+11     nospu   execve                          sys_execve                      compat_sys_execve
+12     common  chdir                           sys_chdir
+13     common  time                            sys_time                        compat_sys_time
+14     common  mknod                           sys_mknod
+15     common  chmod                           sys_chmod
+16     common  lchown                          sys_lchown
+17     common  break                           sys_ni_syscall
+18     32      oldstat                         sys_stat                        sys_ni_syscall
+18     64      oldstat                         sys_ni_syscall
+18     spu     oldstat                         sys_ni_syscall
+19     common  lseek                           sys_lseek                       compat_sys_lseek
+20     common  getpid                          sys_getpid
+21     nospu   mount                           sys_mount                       compat_sys_mount
+22     32      umount                          sys_oldumount
+22     64      umount                          sys_ni_syscall
+22     spu     umount                          sys_ni_syscall
+23     common  setuid                          sys_setuid
+24     common  getuid                          sys_getuid
+25     common  stime                           sys_stime                       compat_sys_stime
+26     nospu   ptrace                          sys_ptrace                      compat_sys_ptrace
+27     common  alarm                           sys_alarm
+28     32      oldfstat                        sys_fstat                       sys_ni_syscall
+28     64      oldfstat                        sys_ni_syscall
+28     spu     oldfstat                        sys_ni_syscall
+29     nospu   pause                           sys_pause
+30     nospu   utime                           sys_utime                       compat_sys_utime
+31     common  stty                            sys_ni_syscall
+32     common  gtty                            sys_ni_syscall
+33     common  access                          sys_access
+34     common  nice                            sys_nice
+35     common  ftime                           sys_ni_syscall
+36     common  sync                            sys_sync
+37     common  kill                            sys_kill
+38     common  rename                          sys_rename
+39     common  mkdir                           sys_mkdir
+40     common  rmdir                           sys_rmdir
+41     common  dup                             sys_dup
+42     common  pipe                            sys_pipe
+43     common  times                           sys_times                       compat_sys_times
+44     common  prof                            sys_ni_syscall
+45     common  brk                             sys_brk
+46     common  setgid                          sys_setgid
+47     common  getgid                          sys_getgid
+48     nospu   signal                          sys_signal
+49     common  geteuid                         sys_geteuid
+50     common  getegid                         sys_getegid
+51     nospu   acct                            sys_acct
+52     nospu   umount2                         sys_umount
+53     common  lock                            sys_ni_syscall
+54     common  ioctl                           sys_ioctl                       compat_sys_ioctl
+55     common  fcntl                           sys_fcntl                       compat_sys_fcntl
+56     common  mpx                             sys_ni_syscall
+57     common  setpgid                         sys_setpgid
+58     common  ulimit                          sys_ni_syscall
+59     32      oldolduname                     sys_olduname
+59     64      oldolduname                     sys_ni_syscall
+59     spu     oldolduname                     sys_ni_syscall
+60     common  umask                           sys_umask
+61     common  chroot                          sys_chroot
+62     nospu   ustat                           sys_ustat                       compat_sys_ustat
+63     common  dup2                            sys_dup2
+64     common  getppid                         sys_getppid
+65     common  getpgrp                         sys_getpgrp
+66     common  setsid                          sys_setsid
+67     32      sigaction                       sys_sigaction                   compat_sys_sigaction
+67     64      sigaction                       sys_ni_syscall
+67     spu     sigaction                       sys_ni_syscall
+68     common  sgetmask                        sys_sgetmask
+69     common  ssetmask                        sys_ssetmask
+70     common  setreuid                        sys_setreuid
+71     common  setregid                        sys_setregid
+72     32      sigsuspend                      sys_sigsuspend
+72     64      sigsuspend                      sys_ni_syscall
+72     spu     sigsuspend                      sys_ni_syscall
+73     32      sigpending                      sys_sigpending                  compat_sys_sigpending
+73     64      sigpending                      sys_ni_syscall
+73     spu     sigpending                      sys_ni_syscall
+74     common  sethostname                     sys_sethostname
+75     common  setrlimit                       sys_setrlimit                   compat_sys_setrlimit
+76     32      getrlimit                       sys_old_getrlimit               compat_sys_old_getrlimit
+76     64      getrlimit                       sys_ni_syscall
+76     spu     getrlimit                       sys_ni_syscall
+77     common  getrusage                       sys_getrusage                   compat_sys_getrusage
+78     common  gettimeofday                    sys_gettimeofday                compat_sys_gettimeofday
+79     common  settimeofday                    sys_settimeofday                compat_sys_settimeofday
+80     common  getgroups                       sys_getgroups
+81     common  setgroups                       sys_setgroups
+82     32      select                          ppc_select                      sys_ni_syscall
+82     64      select                          sys_ni_syscall
+82     spu     select                          sys_ni_syscall
+83     common  symlink                         sys_symlink
+84     32      oldlstat                        sys_lstat                       sys_ni_syscall
+84     64      oldlstat                        sys_ni_syscall
+84     spu     oldlstat                        sys_ni_syscall
+85     common  readlink                        sys_readlink
+86     nospu   uselib                          sys_uselib
+87     nospu   swapon                          sys_swapon
+88     nospu   reboot                          sys_reboot
+89     32      readdir                         sys_old_readdir                 compat_sys_old_readdir
+89     64      readdir                         sys_ni_syscall
+89     spu     readdir                         sys_ni_syscall
+90     common  mmap                            sys_mmap
+91     common  munmap                          sys_munmap
+92     common  truncate                        sys_truncate                    compat_sys_truncate
+93     common  ftruncate                       sys_ftruncate                   compat_sys_ftruncate
+94     common  fchmod                          sys_fchmod
+95     common  fchown                          sys_fchown
+96     common  getpriority                     sys_getpriority
+97     common  setpriority                     sys_setpriority
+98     common  profil                          sys_ni_syscall
+99     nospu   statfs                          sys_statfs                      compat_sys_statfs
+100    nospu   fstatfs                         sys_fstatfs                     compat_sys_fstatfs
+101    common  ioperm                          sys_ni_syscall
+102    common  socketcall                      sys_socketcall                  compat_sys_socketcall
+103    common  syslog                          sys_syslog
+104    common  setitimer                       sys_setitimer                   compat_sys_setitimer
+105    common  getitimer                       sys_getitimer                   compat_sys_getitimer
+106    common  stat                            sys_newstat                     compat_sys_newstat
+107    common  lstat                           sys_newlstat                    compat_sys_newlstat
+108    common  fstat                           sys_newfstat                    compat_sys_newfstat
+109    32      olduname                        sys_uname
+109    64      olduname                        sys_ni_syscall
+109    spu     olduname                        sys_ni_syscall
+110    common  iopl                            sys_ni_syscall
+111    common  vhangup                         sys_vhangup
+112    common  idle                            sys_ni_syscall
+113    common  vm86                            sys_ni_syscall
+114    common  wait4                           sys_wait4                       compat_sys_wait4
+115    nospu   swapoff                         sys_swapoff
+116    common  sysinfo                         sys_sysinfo                     compat_sys_sysinfo
+117    nospu   ipc                             sys_ipc                         compat_sys_ipc
+118    common  fsync                           sys_fsync
+119    32      sigreturn                       sys_sigreturn                   compat_sys_sigreturn
+119    64      sigreturn                       sys_ni_syscall
+119    spu     sigreturn                       sys_ni_syscall
+120    nospu   clone                           ppc_clone
+121    common  setdomainname                   sys_setdomainname
+122    common  uname                           sys_newuname
+123    common  modify_ldt                      sys_ni_syscall
+124    common  adjtimex                        sys_adjtimex                    compat_sys_adjtimex
+125    common  mprotect                        sys_mprotect
+126    32      sigprocmask                     sys_sigprocmask                 compat_sys_sigprocmask
+126    64      sigprocmask                     sys_ni_syscall
+126    spu     sigprocmask                     sys_ni_syscall
+127    common  create_module                   sys_ni_syscall
+128    nospu   init_module                     sys_init_module
+129    nospu   delete_module                   sys_delete_module
+130    common  get_kernel_syms                 sys_ni_syscall
+131    nospu   quotactl                        sys_quotactl
+132    common  getpgid                         sys_getpgid
+133    common  fchdir                          sys_fchdir
+134    common  bdflush                         sys_bdflush
+135    common  sysfs                           sys_sysfs
+136    32      personality                     sys_personality                 ppc64_personality
+136    64      personality                     ppc64_personality
+136    spu     personality                     ppc64_personality
+137    common  afs_syscall                     sys_ni_syscall
+138    common  setfsuid                        sys_setfsuid
+139    common  setfsgid                        sys_setfsgid
+140    common  _llseek                         sys_llseek
+141    common  getdents                        sys_getdents                    compat_sys_getdents
+142    common  _newselect                      sys_select                      compat_sys_select
+143    common  flock                           sys_flock
+144    common  msync                           sys_msync
+145    common  readv                           sys_readv                       compat_sys_readv
+146    common  writev                          sys_writev                      compat_sys_writev
+147    common  getsid                          sys_getsid
+148    common  fdatasync                       sys_fdatasync
+149    nospu   _sysctl                         sys_sysctl                      compat_sys_sysctl
+150    common  mlock                           sys_mlock
+151    common  munlock                         sys_munlock
+152    common  mlockall                        sys_mlockall
+153    common  munlockall                      sys_munlockall
+154    common  sched_setparam                  sys_sched_setparam
+155    common  sched_getparam                  sys_sched_getparam
+156    common  sched_setscheduler              sys_sched_setscheduler
+157    common  sched_getscheduler              sys_sched_getscheduler
+158    common  sched_yield                     sys_sched_yield
+159    common  sched_get_priority_max          sys_sched_get_priority_max
+160    common  sched_get_priority_min          sys_sched_get_priority_min
+161    common  sched_rr_get_interval           sys_sched_rr_get_interval       compat_sys_sched_rr_get_interval
+162    common  nanosleep                       sys_nanosleep                   compat_sys_nanosleep
+163    common  mremap                          sys_mremap
+164    common  setresuid                       sys_setresuid
+165    common  getresuid                       sys_getresuid
+166    common  query_module                    sys_ni_syscall
+167    common  poll                            sys_poll
+168    common  nfsservctl                      sys_ni_syscall
+169    common  setresgid                       sys_setresgid
+170    common  getresgid                       sys_getresgid
+171    common  prctl                           sys_prctl
+172    nospu   rt_sigreturn                    sys_rt_sigreturn                compat_sys_rt_sigreturn
+173    nospu   rt_sigaction                    sys_rt_sigaction                compat_sys_rt_sigaction
+174    nospu   rt_sigprocmask                  sys_rt_sigprocmask              compat_sys_rt_sigprocmask
+175    nospu   rt_sigpending                   sys_rt_sigpending               compat_sys_rt_sigpending
+176    nospu   rt_sigtimedwait                 sys_rt_sigtimedwait             compat_sys_rt_sigtimedwait
+177    nospu   rt_sigqueueinfo                 sys_rt_sigqueueinfo             compat_sys_rt_sigqueueinfo
+178    nospu   rt_sigsuspend                   sys_rt_sigsuspend               compat_sys_rt_sigsuspend
+179    common  pread64                         sys_pread64                     compat_sys_pread64
+180    common  pwrite64                        sys_pwrite64                    compat_sys_pwrite64
+181    common  chown                           sys_chown
+182    common  getcwd                          sys_getcwd
+183    common  capget                          sys_capget
+184    common  capset                          sys_capset
+185    nospu   sigaltstack                     sys_sigaltstack                 compat_sys_sigaltstack
+186    32      sendfile                        sys_sendfile                    compat_sys_sendfile
+186    64      sendfile                        sys_sendfile64
+186    spu     sendfile                        sys_sendfile64
+187    common  getpmsg                         sys_ni_syscall
+188    common  putpmsg                         sys_ni_syscall
+189    nospu   vfork                           ppc_vfork
+190    common  ugetrlimit                      sys_getrlimit                   compat_sys_getrlimit
+191    common  readahead                       sys_readahead                   compat_sys_readahead
+192    32      mmap2                           sys_mmap2                       compat_sys_mmap2
+193    32      truncate64                      sys_truncate64                  compat_sys_truncate64
+194    32      ftruncate64                     sys_ftruncate64                 compat_sys_ftruncate64
+195    32      stat64                          sys_stat64
+196    32      lstat64                         sys_lstat64
+197    32      fstat64                         sys_fstat64
+198    nospu   pciconfig_read                  sys_pciconfig_read
+199    nospu   pciconfig_write                 sys_pciconfig_write
+200    nospu   pciconfig_iobase                sys_pciconfig_iobase
+201    common  multiplexer                     sys_ni_syscall
+202    common  getdents64                      sys_getdents64
+203    common  pivot_root                      sys_pivot_root
+204    32      fcntl64                         sys_fcntl64                     compat_sys_fcntl64
+205    common  madvise                         sys_madvise
+206    common  mincore                         sys_mincore
+207    common  gettid                          sys_gettid
+208    common  tkill                           sys_tkill
+209    common  setxattr                        sys_setxattr
+210    common  lsetxattr                       sys_lsetxattr
+211    common  fsetxattr                       sys_fsetxattr
+212    common  getxattr                        sys_getxattr
+213    common  lgetxattr                       sys_lgetxattr
+214    common  fgetxattr                       sys_fgetxattr
+215    common  listxattr                       sys_listxattr
+216    common  llistxattr                      sys_llistxattr
+217    common  flistxattr                      sys_flistxattr
+218    common  removexattr                     sys_removexattr
+219    common  lremovexattr                    sys_lremovexattr
+220    common  fremovexattr                    sys_fremovexattr
+221    common  futex                           sys_futex                       compat_sys_futex
+222    common  sched_setaffinity               sys_sched_setaffinity           compat_sys_sched_setaffinity
+223    common  sched_getaffinity               sys_sched_getaffinity           compat_sys_sched_getaffinity
+# 224 unused
+225    common  tuxcall                         sys_ni_syscall
+226    32      sendfile64                      sys_sendfile64                  compat_sys_sendfile64
+227    common  io_setup                        sys_io_setup                    compat_sys_io_setup
+228    common  io_destroy                      sys_io_destroy
+229    common  io_getevents                    sys_io_getevents                compat_sys_io_getevents
+230    common  io_submit                       sys_io_submit                   compat_sys_io_submit
+231    common  io_cancel                       sys_io_cancel
+232    nospu   set_tid_address                 sys_set_tid_address
+233    common  fadvise64                       sys_fadvise64                   ppc32_fadvise64
+234    nospu   exit_group                      sys_exit_group
+235    nospu   lookup_dcookie                  sys_lookup_dcookie              compat_sys_lookup_dcookie
+236    common  epoll_create                    sys_epoll_create
+237    common  epoll_ctl                       sys_epoll_ctl
+238    common  epoll_wait                      sys_epoll_wait
+239    common  remap_file_pages                sys_remap_file_pages
+240    common  timer_create                    sys_timer_create                compat_sys_timer_create
+241    common  timer_settime                   sys_timer_settime               compat_sys_timer_settime
+242    common  timer_gettime                   sys_timer_gettime               compat_sys_timer_gettime
+243    common  timer_getoverrun                sys_timer_getoverrun
+244    common  timer_delete                    sys_timer_delete
+245    common  clock_settime                   sys_clock_settime               compat_sys_clock_settime
+246    common  clock_gettime                   sys_clock_gettime               compat_sys_clock_gettime
+247    common  clock_getres                    sys_clock_getres                compat_sys_clock_getres
+248    common  clock_nanosleep                 sys_clock_nanosleep             compat_sys_clock_nanosleep
+249    32      swapcontext                     ppc_swapcontext                 ppc32_swapcontext
+249    64      swapcontext                     ppc64_swapcontext
+249    spu     swapcontext                     sys_ni_syscall
+250    common  tgkill                          sys_tgkill
+251    common  utimes                          sys_utimes                      compat_sys_utimes
+252    common  statfs64                        sys_statfs64                    compat_sys_statfs64
+253    common  fstatfs64                       sys_fstatfs64                   compat_sys_fstatfs64
+254    32      fadvise64_64                    ppc_fadvise64_64
+254    spu     fadvise64_64                    sys_ni_syscall
+255    common  rtas                            sys_rtas
+256    32      sys_debug_setcontext            sys_debug_setcontext            sys_ni_syscall
+256    64      sys_debug_setcontext            sys_ni_syscall
+256    spu     sys_debug_setcontext            sys_ni_syscall
+# 257 reserved for vserver
+258    nospu   migrate_pages                   sys_migrate_pages               compat_sys_migrate_pages
+259    nospu   mbind                           sys_mbind                       compat_sys_mbind
+260    nospu   get_mempolicy                   sys_get_mempolicy               compat_sys_get_mempolicy
+261    nospu   set_mempolicy                   sys_set_mempolicy               compat_sys_set_mempolicy
+262    nospu   mq_open                         sys_mq_open                     compat_sys_mq_open
+263    nospu   mq_unlink                       sys_mq_unlink
+264    nospu   mq_timedsend                    sys_mq_timedsend                compat_sys_mq_timedsend
+265    nospu   mq_timedreceive                 sys_mq_timedreceive             compat_sys_mq_timedreceive
+266    nospu   mq_notify                       sys_mq_notify                   compat_sys_mq_notify
+267    nospu   mq_getsetattr                   sys_mq_getsetattr               compat_sys_mq_getsetattr
+268    nospu   kexec_load                      sys_kexec_load                  compat_sys_kexec_load
+269    nospu   add_key                         sys_add_key
+270    nospu   request_key                     sys_request_key
+271    nospu   keyctl                          sys_keyctl                      compat_sys_keyctl
+272    nospu   waitid                          sys_waitid                      compat_sys_waitid
+273    nospu   ioprio_set                      sys_ioprio_set
+274    nospu   ioprio_get                      sys_ioprio_get
+275    nospu   inotify_init                    sys_inotify_init
+276    nospu   inotify_add_watch               sys_inotify_add_watch
+277    nospu   inotify_rm_watch                sys_inotify_rm_watch
+278    nospu   spu_run                         sys_spu_run
+279    nospu   spu_create                      sys_spu_create
+280    nospu   pselect6                        sys_pselect6                    compat_sys_pselect6
+281    nospu   ppoll                           sys_ppoll                       compat_sys_ppoll
+282    common  unshare                         sys_unshare
+283    common  splice                          sys_splice
+284    common  tee                             sys_tee
+285    common  vmsplice                        sys_vmsplice                    compat_sys_vmsplice
+286    common  openat                          sys_openat                      compat_sys_openat
+287    common  mkdirat                         sys_mkdirat
+288    common  mknodat                         sys_mknodat
+289    common  fchownat                        sys_fchownat
+290    common  futimesat                       sys_futimesat                   compat_sys_futimesat
+291    32      fstatat64                       sys_fstatat64
+291    64      newfstatat                      sys_newfstatat
+291    spu     newfstatat                      sys_newfstatat
+292    common  unlinkat                        sys_unlinkat
+293    common  renameat                        sys_renameat
+294    common  linkat                          sys_linkat
+295    common  symlinkat                       sys_symlinkat
+296    common  readlinkat                      sys_readlinkat
+297    common  fchmodat                        sys_fchmodat
+298    common  faccessat                       sys_faccessat
+299    common  get_robust_list                 sys_get_robust_list             compat_sys_get_robust_list
+300    common  set_robust_list                 sys_set_robust_list             compat_sys_set_robust_list
+301    common  move_pages                      sys_move_pages                  compat_sys_move_pages
+302    common  getcpu                          sys_getcpu
+303    nospu   epoll_pwait                     sys_epoll_pwait                 compat_sys_epoll_pwait
+304    common  utimensat                       sys_utimensat                   compat_sys_utimensat
+305    common  signalfd                        sys_signalfd                    compat_sys_signalfd
+306    common  timerfd_create                  sys_timerfd_create
+307    common  eventfd                         sys_eventfd
+308    common  sync_file_range2                sys_sync_file_range2            compat_sys_sync_file_range2
+309    nospu   fallocate                       sys_fallocate                   compat_sys_fallocate
+310    nospu   subpage_prot                    sys_subpage_prot
+311    common  timerfd_settime                 sys_timerfd_settime             compat_sys_timerfd_settime
+312    common  timerfd_gettime                 sys_timerfd_gettime             compat_sys_timerfd_gettime
+313    common  signalfd4                       sys_signalfd4                   compat_sys_signalfd4
+314    common  eventfd2                        sys_eventfd2
+315    common  epoll_create1                   sys_epoll_create1
+316    common  dup3                            sys_dup3
+317    common  pipe2                           sys_pipe2
+318    nospu   inotify_init1                   sys_inotify_init1
+319    common  perf_event_open                 sys_perf_event_open
+320    common  preadv                          sys_preadv                      compat_sys_preadv
+321    common  pwritev                         sys_pwritev                     compat_sys_pwritev
+322    nospu   rt_tgsigqueueinfo               sys_rt_tgsigqueueinfo           compat_sys_rt_tgsigqueueinfo
+323    nospu   fanotify_init                   sys_fanotify_init
+324    nospu   fanotify_mark                   sys_fanotify_mark               compat_sys_fanotify_mark
+325    common  prlimit64                       sys_prlimit64
+326    common  socket                          sys_socket
+327    common  bind                            sys_bind
+328    common  connect                         sys_connect
+329    common  listen                          sys_listen
+330    common  accept                          sys_accept
+331    common  getsockname                     sys_getsockname
+332    common  getpeername                     sys_getpeername
+333    common  socketpair                      sys_socketpair
+334    common  send                            sys_send
+335    common  sendto                          sys_sendto
+336    common  recv                            sys_recv                        compat_sys_recv
+337    common  recvfrom                        sys_recvfrom                    compat_sys_recvfrom
+338    common  shutdown                        sys_shutdown
+339    common  setsockopt                      sys_setsockopt                  compat_sys_setsockopt
+340    common  getsockopt                      sys_getsockopt                  compat_sys_getsockopt
+341    common  sendmsg                         sys_sendmsg                     compat_sys_sendmsg
+342    common  recvmsg                         sys_recvmsg                     compat_sys_recvmsg
+343    common  recvmmsg                        sys_recvmmsg                    compat_sys_recvmmsg
+344    common  accept4                         sys_accept4
+345    common  name_to_handle_at               sys_name_to_handle_at
+346    common  open_by_handle_at               sys_open_by_handle_at           compat_sys_open_by_handle_at
+347    common  clock_adjtime                   sys_clock_adjtime               compat_sys_clock_adjtime
+348    common  syncfs                          sys_syncfs
+349    common  sendmmsg                        sys_sendmmsg                    compat_sys_sendmmsg
+350    common  setns                           sys_setns
+351    nospu   process_vm_readv                sys_process_vm_readv            compat_sys_process_vm_readv
+352    nospu   process_vm_writev               sys_process_vm_writev           compat_sys_process_vm_writev
+353    nospu   finit_module                    sys_finit_module
+354    nospu   kcmp                            sys_kcmp
+355    common  sched_setattr                   sys_sched_setattr
+356    common  sched_getattr                   sys_sched_getattr
+357    common  renameat2                       sys_renameat2
+358    common  seccomp                         sys_seccomp
+359    common  getrandom                       sys_getrandom
+360    common  memfd_create                    sys_memfd_create
+361    common  bpf                             sys_bpf
+362    nospu   execveat                        sys_execveat                    compat_sys_execveat
+363    32      switch_endian                   sys_ni_syscall
+363    64      switch_endian                   ppc_switch_endian
+363    spu     switch_endian                   sys_ni_syscall
+364    common  userfaultfd                     sys_userfaultfd
+365    common  membarrier                      sys_membarrier
+378    nospu   mlock2                          sys_mlock2
+379    nospu   copy_file_range                 sys_copy_file_range
+380    common  preadv2                         sys_preadv2                     compat_sys_preadv2
+381    common  pwritev2                        sys_pwritev2                    compat_sys_pwritev2
+382    nospu   kexec_file_load                 sys_kexec_file_load
+383    nospu   statx                           sys_statx
+384    nospu   pkey_alloc                      sys_pkey_alloc
+385    nospu   pkey_free                       sys_pkey_free
+386    nospu   pkey_mprotect                   sys_pkey_mprotect
+387    nospu   rseq                            sys_rseq
+388    nospu   io_pgetevents                   sys_io_pgetevents               compat_sys_io_pgetevents
index 1076393..e18a355 100644 (file)
@@ -63,7 +63,8 @@ static const char *reg_names[] = {
        [PERF_REG_POWERPC_TRAP] = "trap",
        [PERF_REG_POWERPC_DAR] = "dar",
        [PERF_REG_POWERPC_DSISR] = "dsisr",
-       [PERF_REG_POWERPC_SIER] = "sier"
+       [PERF_REG_POWERPC_SIER] = "sier",
+       [PERF_REG_POWERPC_MMCRA] = "mmcra"
 };
 
 static inline const char *perf_reg_name(int id)
index 2e65953..ba98bd0 100644 (file)
@@ -2,6 +2,7 @@ libperf-y += header.o
 libperf-y += sym-handling.o
 libperf-y += kvm-stat.o
 libperf-y += perf_regs.o
+libperf-y += mem-events.o
 
 libperf-$(CONFIG_DWARF) += dwarf-regs.o
 libperf-$(CONFIG_DWARF) += skip-callchain-idx.o
diff --git a/tools/perf/arch/powerpc/util/mem-events.c b/tools/perf/arch/powerpc/util/mem-events.c
new file mode 100644 (file)
index 0000000..d08311f
--- /dev/null
@@ -0,0 +1,11 @@
+// SPDX-License-Identifier: GPL-2.0
+#include "mem-events.h"
+
+/* PowerPC does not support 'ldlat' parameter. */
+char *perf_mem_events__name(int i)
+{
+       if (i == PERF_MEM_EVENTS__LOAD)
+               return (char *) "cpu/mem-loads/";
+
+       return (char *) "cpu/mem-stores/";
+}
index 07fcd97..34d5134 100644 (file)
@@ -53,6 +53,7 @@ const struct sample_reg sample_reg_masks[] = {
        SMPL_REG(dar, PERF_REG_POWERPC_DAR),
        SMPL_REG(dsisr, PERF_REG_POWERPC_DSISR),
        SMPL_REG(sier, PERF_REG_POWERPC_SIER),
+       SMPL_REG(mmcra, PERF_REG_POWERPC_MMCRA),
        SMPL_REG_END
 };
 
index d079f36..ac221f1 100644 (file)
@@ -1681,13 +1681,8 @@ static void perf_sample__fprint_metric(struct perf_script *script,
                .force_header = false,
        };
        struct perf_evsel *ev2;
-       static bool init;
        u64 val;
 
-       if (!init) {
-               perf_stat__init_shadow_stats();
-               init = true;
-       }
        if (!evsel->stats)
                perf_evlist__alloc_stats(script->session->evlist, false);
        if (evsel_script(evsel->leader)->gnum++ == 0)
@@ -1794,7 +1789,7 @@ static void process_event(struct perf_script *script,
                return;
        }
 
-       if (PRINT_FIELD(TRACE)) {
+       if (PRINT_FIELD(TRACE) && sample->raw_data) {
                event_format__fprintf(evsel->tp_format, sample->cpu,
                                      sample->raw_data, sample->raw_size, fp);
        }
@@ -2359,6 +2354,8 @@ static int __cmd_script(struct perf_script *script)
 
        signal(SIGINT, sig_handler);
 
+       perf_stat__init_shadow_stats();
+
        /* override event processing functions */
        if (script->show_task_events) {
                script->tool.comm = process_comm_event;
index 1410d66..63a3afc 100644 (file)
@@ -561,7 +561,8 @@ try_again:
                                        break;
                        }
                }
-               wait4(child_pid, &status, 0, &stat_config.ru_data);
+               if (child_pid != -1)
+                       wait4(child_pid, &status, 0, &stat_config.ru_data);
 
                if (workload_exec_errno) {
                        const char *emsg = str_error_r(workload_exec_errno, msg, sizeof(msg));
index fe3ecfb..f64e312 100644 (file)
@@ -1028,12 +1028,7 @@ out_err:
 
 static int callchain_param__setup_sample_type(struct callchain_param *callchain)
 {
-       if (!perf_hpp_list.sym) {
-               if (callchain->enabled) {
-                       ui__error("Selected -g but \"sym\" not present in --sort/-s.");
-                       return -EINVAL;
-               }
-       } else if (callchain->mode != CHAIN_NONE) {
+       if (callchain->mode != CHAIN_NONE) {
                if (callchain_register_param(callchain) < 0) {
                        ui__error("Can't register callchain params.\n");
                        return -EINVAL;
index adbf281..b36061c 100644 (file)
@@ -1758,6 +1758,7 @@ static int trace__printf_interrupted_entry(struct trace *trace)
 {
        struct thread_trace *ttrace;
        size_t printed;
+       int len;
 
        if (trace->failure_only || trace->current == NULL)
                return 0;
@@ -1768,9 +1769,14 @@ static int trace__printf_interrupted_entry(struct trace *trace)
                return 0;
 
        printed  = trace__fprintf_entry_head(trace, trace->current, 0, false, ttrace->entry_time, trace->output);
-       printed += fprintf(trace->output, ")%-*s ...\n", trace->args_alignment, ttrace->entry_str);
-       ttrace->entry_pending = false;
+       printed += len = fprintf(trace->output, "%s)", ttrace->entry_str);
+
+       if (len < trace->args_alignment - 4)
+               printed += fprintf(trace->output, "%-*s", trace->args_alignment - 4 - len, " ");
+
+       printed += fprintf(trace->output, " ...\n");
 
+       ttrace->entry_pending = false;
        ++trace->nr_events_printed;
 
        return printed;
@@ -2026,9 +2032,10 @@ static int trace__sys_exit(struct trace *trace, struct perf_evsel *evsel,
        if (ttrace->entry_pending) {
                printed = fprintf(trace->output, "%s", ttrace->entry_str);
        } else {
-               fprintf(trace->output, " ... [");
+               printed += fprintf(trace->output, " ... [");
                color_fprintf(trace->output, PERF_COLOR_YELLOW, "continued");
-               fprintf(trace->output, "]: %s()", sc->name);
+               printed += 9;
+               printed += fprintf(trace->output, "]: %s()", sc->name);
        }
 
        printed++; /* the closing ')' */
@@ -2507,19 +2514,30 @@ static size_t trace__fprintf_thread_summary(struct trace *trace, FILE *fp);
 
 static bool perf_evlist__add_vfs_getname(struct perf_evlist *evlist)
 {
-       struct perf_evsel *evsel = perf_evsel__newtp("probe", "vfs_getname");
+       bool found = false;
+       struct perf_evsel *evsel, *tmp;
+       struct parse_events_error err = { .idx = 0, };
+       int ret = parse_events(evlist, "probe:vfs_getname*", &err);
 
-       if (IS_ERR(evsel))
+       if (ret)
                return false;
 
-       if (perf_evsel__field(evsel, "pathname") == NULL) {
+       evlist__for_each_entry_safe(evlist, evsel, tmp) {
+               if (!strstarts(perf_evsel__name(evsel), "probe:vfs_getname"))
+                       continue;
+
+               if (perf_evsel__field(evsel, "pathname")) {
+                       evsel->handler = trace__vfs_getname;
+                       found = true;
+                       continue;
+               }
+
+               list_del_init(&evsel->node);
+               evsel->evlist = NULL;
                perf_evsel__delete(evsel);
-               return false;
        }
 
-       evsel->handler = trace__vfs_getname;
-       perf_evlist__add(evlist, evsel);
-       return true;
+       return found;
 }
 
 static struct perf_evsel *perf_evsel__new_pgfault(u64 config)
index 6cb98f8..7b55613 100755 (executable)
@@ -10,6 +10,7 @@ include/uapi/linux/fs.h
 include/uapi/linux/kcmp.h
 include/uapi/linux/kvm.h
 include/uapi/linux/in.h
+include/uapi/linux/mount.h
 include/uapi/linux/perf_event.h
 include/uapi/linux/prctl.h
 include/uapi/linux/sched.h
@@ -49,7 +50,6 @@ arch/parisc/include/uapi/asm/errno.h
 arch/powerpc/include/uapi/asm/errno.h
 arch/sparc/include/uapi/asm/errno.h
 arch/x86/include/uapi/asm/errno.h
-arch/powerpc/include/uapi/asm/unistd.h
 include/asm-generic/bitops/arch_hweight.h
 include/asm-generic/bitops/const_hweight.h
 include/asm-generic/bitops/__fls.h
index 8c0ca0c..aaa5210 100644 (file)
@@ -5,17 +5,17 @@
 #define VDSO__MAP_NAME "[vdso]"
 
 /*
- * Include definition of find_vdso_map() also used in util/vdso.c for
+ * Include definition of find_map() also used in util/vdso.c for
  * building perf.
  */
-#include "util/find-vdso-map.c"
+#include "util/find-map.c"
 
 int main(void)
 {
        void *start, *end;
        size_t size, written;
 
-       if (find_vdso_map(&start, &end))
+       if (find_map(&start, &end, VDSO__MAP_NAME))
                return 1;
 
        size = end - start;
index 44090a9..e952127 100644 (file)
@@ -1,6 +1,8 @@
 #! /usr/bin/python
 # SPDX-License-Identifier: GPL-2.0
 
+from __future__ import print_function
+
 import os
 import sys
 import glob
@@ -8,7 +10,11 @@ import optparse
 import tempfile
 import logging
 import shutil
-import ConfigParser
+
+try:
+    import configparser
+except ImportError:
+    import ConfigParser as configparser
 
 def data_equal(a, b):
     # Allow multiple values in assignment separated by '|'
@@ -100,20 +106,20 @@ class Event(dict):
     def equal(self, other):
         for t in Event.terms:
             log.debug("      [%s] %s %s" % (t, self[t], other[t]));
-            if not self.has_key(t) or not other.has_key(t):
+            if t not in self or t not in other:
                 return False
             if not data_equal(self[t], other[t]):
                 return False
         return True
 
     def optional(self):
-        if self.has_key('optional') and self['optional'] == '1':
+        if 'optional' in self and self['optional'] == '1':
             return True
         return False
 
     def diff(self, other):
         for t in Event.terms:
-            if not self.has_key(t) or not other.has_key(t):
+            if t not in self or t not in other:
                 continue
             if not data_equal(self[t], other[t]):
                 log.warning("expected %s=%s, got %s" % (t, self[t], other[t]))
@@ -134,7 +140,7 @@ class Event(dict):
 #   - expected values assignments
 class Test(object):
     def __init__(self, path, options):
-        parser = ConfigParser.SafeConfigParser()
+        parser = configparser.SafeConfigParser()
         parser.read(path)
 
         log.warning("running '%s'" % path)
@@ -193,7 +199,7 @@ class Test(object):
         return True
 
     def load_events(self, path, events):
-        parser_event = ConfigParser.SafeConfigParser()
+        parser_event = configparser.SafeConfigParser()
         parser_event.read(path)
 
         # The event record section header contains 'event' word,
@@ -207,7 +213,7 @@ class Test(object):
             # Read parent event if there's any
             if (':' in section):
                 base = section[section.index(':') + 1:]
-                parser_base = ConfigParser.SafeConfigParser()
+                parser_base = configparser.SafeConfigParser()
                 parser_base.read(self.test_dir + '/' + base)
                 base_items = parser_base.items('event')
 
@@ -322,9 +328,9 @@ def run_tests(options):
     for f in glob.glob(options.test_dir + '/' + options.test):
         try:
             Test(f, options).run()
-        except Unsup, obj:
+        except Unsup as obj:
             log.warning("unsupp  %s" % obj.getMsg())
-        except Notest, obj:
+        except Notest as obj:
             log.warning("skipped %s" % obj.getMsg())
 
 def setup_log(verbose):
@@ -363,7 +369,7 @@ def main():
     parser.add_option("-p", "--perf",
                       action="store", type="string", dest="perf")
     parser.add_option("-v", "--verbose",
-                      action="count", dest="verbose")
+                      default=0, action="count", dest="verbose")
 
     options, args = parser.parse_args()
     if args:
@@ -373,7 +379,7 @@ def main():
     setup_log(options.verbose)
 
     if not options.test_dir:
-        print 'FAILED no -d option specified'
+        print('FAILED no -d option specified')
         sys.exit(-1)
 
     if not options.test:
@@ -382,8 +388,8 @@ def main():
     try:
         run_tests(options)
 
-    except Fail, obj:
-        print "FAILED %s" % obj.getMsg();
+    except Fail as obj:
+        print("FAILED %s" % obj.getMsg())
         sys.exit(-1)
 
     sys.exit(0)
index 5f8501c..5cbba70 100644 (file)
@@ -17,7 +17,7 @@ static int perf_evsel__test_field(struct perf_evsel *evsel, const char *name,
                return -1;
        }
 
-       is_signed = !!(field->flags | TEP_FIELD_IS_SIGNED);
+       is_signed = !!(field->flags & TEP_FIELD_IS_SIGNED);
        if (should_be_signed && !is_signed) {
                pr_debug("%s: \"%s\" signedness(%d) is wrong, should be %d\n",
                         evsel->name, name, is_signed, should_be_signed);
index 1c16e56..7cb99b4 100644 (file)
@@ -13,7 +13,8 @@ add_probe_vfs_getname() {
        local verbose=$1
        if [ $had_vfs_getname -eq 1 ] ; then
                line=$(perf probe -L getname_flags 2>&1 | egrep 'result.*=.*filename;' | sed -r 's/[[:space:]]+([[:digit:]]+)[[:space:]]+result->uptr.*/\1/')
-               perf probe $verbose "vfs_getname=getname_flags:${line} pathname=result->name:string"
+               perf probe -q       "vfs_getname=getname_flags:${line} pathname=result->name:string" || \
+               perf probe $verbose "vfs_getname=getname_flags:${line} pathname=filename:string"
        fi
 }
 
index b82f55f..399f18c 100644 (file)
@@ -119,4 +119,9 @@ int test__arch_unwind_sample(struct perf_sample *sample,
                             struct thread *thread);
 #endif
 #endif
+
+#if defined(__arm__)
+int test__vectors_page(struct test *test, int subtest);
+#endif
+
 #endif /* TESTS_H */
index 4554757..847850b 100755 (executable)
@@ -5,11 +5,11 @@
 
 printf "static const char *mount_flags[] = {\n"
 regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MS_([[:alnum:]_]+)[[:space:]]+([[:digit:]]+)[[:space:]]*.*'
-egrep $regex ${header_dir}/fs.h | egrep -v '(MSK|VERBOSE|MGC_VAL)\>' | \
+egrep $regex ${header_dir}/mount.h | egrep -v '(MSK|VERBOSE|MGC_VAL)\>' | \
        sed -r "s/$regex/\2 \2 \1/g" | sort -n | \
        xargs printf "\t[%s ? (ilog2(%s) + 1) : 0] = \"%s\",\n"
 regex='^[[:space:]]*#[[:space:]]*define[[:space:]]+MS_([[:alnum:]_]+)[[:space:]]+\(1<<([[:digit:]]+)\)[[:space:]]*.*'
-egrep $regex ${header_dir}/fs.h | \
+egrep $regex ${header_dir}/mount.h | \
        sed -r "s/$regex/\2 \1/g" | \
        xargs printf "\t[%s + 1] = \"%s\",\n"
 printf "};\n"
index d32f8f1..3109d7b 100755 (executable)
@@ -4,7 +4,7 @@
 [ $# -eq 1 ] && header_dir=$1 || header_dir=tools/include/uapi/linux/
 
 printf "static const char *prctl_options[] = {\n"
-regex='^#define[[:space:]]+PR_([GS]ET\w+)[[:space:]]*([[:xdigit:]]+).*'
+regex='^#define[[:space:]]+PR_(\w+)[[:space:]]*([[:xdigit:]]+).*'
 egrep $regex ${header_dir}/prctl.h | grep -v PR_SET_PTRACER | \
        sed -r "s/$regex/\2 \1/g"       | \
        sort -n | xargs printf "\t[%s] = \"%s\",\n"
index 1d00e5e..82e16bf 100644 (file)
@@ -224,20 +224,24 @@ static unsigned int annotate_browser__refresh(struct ui_browser *browser)
        return ret;
 }
 
-static int disasm__cmp(struct annotation_line *a, struct annotation_line *b)
+static double disasm__cmp(struct annotation_line *a, struct annotation_line *b,
+                                                 int percent_type)
 {
        int i;
 
        for (i = 0; i < a->data_nr; i++) {
-               if (a->data[i].percent == b->data[i].percent)
+               if (a->data[i].percent[percent_type] == b->data[i].percent[percent_type])
                        continue;
-               return a->data[i].percent < b->data[i].percent;
+               return a->data[i].percent[percent_type] -
+                          b->data[i].percent[percent_type];
        }
        return 0;
 }
 
-static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line *al)
+static void disasm_rb_tree__insert(struct annotate_browser *browser,
+                               struct annotation_line *al)
 {
+       struct rb_root *root = &browser->entries;
        struct rb_node **p = &root->rb_node;
        struct rb_node *parent = NULL;
        struct annotation_line *l;
@@ -246,7 +250,7 @@ static void disasm_rb_tree__insert(struct rb_root *root, struct annotation_line
                parent = *p;
                l = rb_entry(parent, struct annotation_line, rb_node);
 
-               if (disasm__cmp(al, l))
+               if (disasm__cmp(al, l, browser->opts->percent_type) < 0)
                        p = &(*p)->rb_left;
                else
                        p = &(*p)->rb_right;
@@ -329,7 +333,7 @@ static void annotate_browser__calc_percent(struct annotate_browser *browser,
                        RB_CLEAR_NODE(&pos->al.rb_node);
                        continue;
                }
-               disasm_rb_tree__insert(&browser->entries, &pos->al);
+               disasm_rb_tree__insert(browser, &pos->al);
        }
        pthread_mutex_unlock(&notes->lock);
 
index ac9805e..70de8f6 100644 (file)
@@ -1723,15 +1723,14 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
        err = asprintf(&command,
                 "%s %s%s --start-address=0x%016" PRIx64
                 " --stop-address=0x%016" PRIx64
-                " -l -d %s %s -C \"%s\" 2>/dev/null|grep -v \"%s:\"|expand",
+                " -l -d %s %s -C \"$1\" 2>/dev/null|grep -v \"$1:\"|expand",
                 opts->objdump_path ?: "objdump",
                 opts->disassembler_style ? "-M " : "",
                 opts->disassembler_style ?: "",
                 map__rip_2objdump(map, sym->start),
                 map__rip_2objdump(map, sym->end),
                 opts->show_asm_raw ? "" : "--no-show-raw",
-                opts->annotate_src ? "-S" : "",
-                symfs_filename, symfs_filename);
+                opts->annotate_src ? "-S" : "");
 
        if (err < 0) {
                pr_err("Failure allocating memory for the command to run\n");
@@ -1756,7 +1755,8 @@ static int symbol__disassemble(struct symbol *sym, struct annotate_args *args)
                close(stdout_fd[0]);
                dup2(stdout_fd[1], 1);
                close(stdout_fd[1]);
-               execl("/bin/sh", "sh", "-c", command, NULL);
+               execl("/bin/sh", "sh", "-c", command, "--", symfs_filename,
+                     NULL);
                perror(command);
                exit(-1);
        }
index 8951250..39c0004 100644 (file)
@@ -160,7 +160,7 @@ getBPFObjectFromModule(llvm::Module *Module)
        }
        PM.run(*Module);
 
-       return std::move(Buffer);
+       return Buffer;
 }
 
 }
index 32ef7bd..dc2212e 100644 (file)
@@ -766,6 +766,7 @@ static enum match_result match_chain(struct callchain_cursor_node *node,
                        cnode->cycles_count += node->branch_flags.cycles;
                        cnode->iter_count += node->nr_loop_iter;
                        cnode->iter_cycles += node->iter_cycles;
+                       cnode->from_count++;
                }
        }
 
@@ -1345,10 +1346,10 @@ static int branch_to_str(char *bf, int bfsize,
 static int branch_from_str(char *bf, int bfsize,
                           u64 branch_count,
                           u64 cycles_count, u64 iter_count,
-                          u64 iter_cycles)
+                          u64 iter_cycles, u64 from_count)
 {
        int printed = 0, i = 0;
-       u64 cycles;
+       u64 cycles, v = 0;
 
        cycles = cycles_count / branch_count;
        if (cycles) {
@@ -1357,14 +1358,16 @@ static int branch_from_str(char *bf, int bfsize,
                                bf + printed, bfsize - printed);
        }
 
-       if (iter_count) {
-               printed += count_pri64_printf(i++, "iter",
-                               iter_count,
-                               bf + printed, bfsize - printed);
+       if (iter_count && from_count) {
+               v = iter_count / from_count;
+               if (v) {
+                       printed += count_pri64_printf(i++, "iter",
+                                       v, bf + printed, bfsize - printed);
 
-               printed += count_pri64_printf(i++, "avg_cycles",
-                               iter_cycles / iter_count,
-                               bf + printed, bfsize - printed);
+                       printed += count_pri64_printf(i++, "avg_cycles",
+                                       iter_cycles / iter_count,
+                                       bf + printed, bfsize - printed);
+               }
        }
 
        if (i)
@@ -1377,6 +1380,7 @@ static int counts_str_build(char *bf, int bfsize,
                             u64 branch_count, u64 predicted_count,
                             u64 abort_count, u64 cycles_count,
                             u64 iter_count, u64 iter_cycles,
+                            u64 from_count,
                             struct branch_type_stat *brtype_stat)
 {
        int printed;
@@ -1389,7 +1393,8 @@ static int counts_str_build(char *bf, int bfsize,
                                predicted_count, abort_count, brtype_stat);
        } else {
                printed = branch_from_str(bf, bfsize, branch_count,
-                               cycles_count, iter_count, iter_cycles);
+                               cycles_count, iter_count, iter_cycles,
+                               from_count);
        }
 
        if (!printed)
@@ -1402,13 +1407,14 @@ static int callchain_counts_printf(FILE *fp, char *bf, int bfsize,
                                   u64 branch_count, u64 predicted_count,
                                   u64 abort_count, u64 cycles_count,
                                   u64 iter_count, u64 iter_cycles,
+                                  u64 from_count,
                                   struct branch_type_stat *brtype_stat)
 {
        char str[256];
 
        counts_str_build(str, sizeof(str), branch_count,
                         predicted_count, abort_count, cycles_count,
-                        iter_count, iter_cycles, brtype_stat);
+                        iter_count, iter_cycles, from_count, brtype_stat);
 
        if (fp)
                return fprintf(fp, "%s", str);
@@ -1422,6 +1428,7 @@ int callchain_list_counts__printf_value(struct callchain_list *clist,
        u64 branch_count, predicted_count;
        u64 abort_count, cycles_count;
        u64 iter_count, iter_cycles;
+       u64 from_count;
 
        branch_count = clist->branch_count;
        predicted_count = clist->predicted_count;
@@ -1429,11 +1436,12 @@ int callchain_list_counts__printf_value(struct callchain_list *clist,
        cycles_count = clist->cycles_count;
        iter_count = clist->iter_count;
        iter_cycles = clist->iter_cycles;
+       from_count = clist->from_count;
 
        return callchain_counts_printf(fp, bf, bfsize, branch_count,
                                       predicted_count, abort_count,
                                       cycles_count, iter_count, iter_cycles,
-                                      &clist->brtype_stat);
+                                      from_count, &clist->brtype_stat);
 }
 
 static void free_callchain_node(struct callchain_node *node)
index 154560b..99d38ac 100644 (file)
@@ -118,6 +118,7 @@ struct callchain_list {
                bool            has_children;
        };
        u64                     branch_count;
+       u64                     from_count;
        u64                     predicted_count;
        u64                     abort_count;
        u64                     cycles_count;
index 1ccbd33..383674f 100644 (file)
@@ -134,7 +134,12 @@ struct cpu_map *cpu_map__new(const char *cpu_list)
        if (!cpu_list)
                return cpu_map__read_all_cpu_map();
 
-       if (!isdigit(*cpu_list))
+       /*
+        * must handle the case of empty cpumap to cover
+        * TOPOLOGY header for NUMA nodes with no CPU
+        * ( e.g., because of CPU hotplug)
+        */
+       if (!isdigit(*cpu_list) && *cpu_list != '\0')
                goto out;
 
        while (isdigit(*cpu_list)) {
@@ -181,8 +186,10 @@ struct cpu_map *cpu_map__new(const char *cpu_list)
 
        if (nr_cpus > 0)
                cpus = cpu_map__trim_new(nr_cpus, tmp_cpus);
-       else
+       else if (*cpu_list != '\0')
                cpus = cpu_map__default_new();
+       else
+               cpus = cpu_map__dummy_new();
 invalid:
        free(tmp_cpus);
 out:
diff --git a/tools/perf/util/find-map.c b/tools/perf/util/find-map.c
new file mode 100644 (file)
index 0000000..7b23005
--- /dev/null
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0
+static int find_map(void **start, void **end, const char *name)
+{
+       FILE *maps;
+       char line[128];
+       int found = 0;
+
+       maps = fopen("/proc/self/maps", "r");
+       if (!maps) {
+               fprintf(stderr, "cannot open maps\n");
+               return -1;
+       }
+
+       while (!found && fgets(line, sizeof(line), maps)) {
+               int m = -1;
+
+               /* We care only about private r-x mappings. */
+               if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n",
+                               start, end, &m))
+                       continue;
+               if (m < 0)
+                       continue;
+
+               if (!strncmp(&line[m], name, strlen(name)))
+                       found = 1;
+       }
+
+       fclose(maps);
+       return !found;
+}
diff --git a/tools/perf/util/find-vdso-map.c b/tools/perf/util/find-vdso-map.c
deleted file mode 100644 (file)
index d7823e3..0000000
+++ /dev/null
@@ -1,31 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-static int find_vdso_map(void **start, void **end)
-{
-       FILE *maps;
-       char line[128];
-       int found = 0;
-
-       maps = fopen("/proc/self/maps", "r");
-       if (!maps) {
-               fprintf(stderr, "vdso: cannot open maps\n");
-               return -1;
-       }
-
-       while (!found && fgets(line, sizeof(line), maps)) {
-               int m = -1;
-
-               /* We care only about private r-x mappings. */
-               if (2 != sscanf(line, "%p-%p r-xp %*x %*x:%*x %*u %n",
-                               start, end, &m))
-                       continue;
-               if (m < 0)
-                       continue;
-
-               if (!strncmp(&line[m], VDSO__MAP_NAME,
-                            sizeof(VDSO__MAP_NAME) - 1))
-                       found = 1;
-       }
-
-       fclose(maps);
-       return !found;
-}
index 6fcb3bc..143f705 100644 (file)
@@ -2005,7 +2005,7 @@ static void save_iterations(struct iterations *iter,
 {
        int i;
 
-       iter->nr_loop_iter = nr;
+       iter->nr_loop_iter++;
        iter->cycles = 0;
 
        for (i = 0; i < nr; i++)
index 93f74d8..42c3e5a 100644 (file)
@@ -28,7 +28,7 @@ struct perf_mem_event perf_mem_events[PERF_MEM_EVENTS__MAX] = {
 static char mem_loads_name[100];
 static bool mem_loads_name__init;
 
-char *perf_mem_events__name(int i)
+char * __weak perf_mem_events__name(int i)
 {
        if (i == PERF_MEM_EVENTS__LOAD) {
                if (!mem_loads_name__init) {
index 8975895..ea523d3 100644 (file)
@@ -391,8 +391,10 @@ void ordered_events__free(struct ordered_events *oe)
         * Current buffer might not have all the events allocated
         * yet, we need to free only allocated ones ...
         */
-       list_del(&oe->buffer->list);
-       ordered_events_buffer__free(oe->buffer, oe->buffer_idx, oe);
+       if (oe->buffer) {
+               list_del(&oe->buffer->list);
+               ordered_events_buffer__free(oe->buffer, oe->buffer_idx, oe);
+       }
 
        /* ... and continue with the rest */
        list_for_each_entry_safe(buffer, tmp, &oe->to_free, list) {
index 63f758c..64d1f36 100644 (file)
@@ -17,6 +17,8 @@ if cc == "clang":
             vars[var] = sub("-mcet", "", vars[var])
         if not clang_has_option("-fcf-protection"):
             vars[var] = sub("-fcf-protection", "", vars[var])
+        if not clang_has_option("-fstack-clash-protection"):
+            vars[var] = sub("-fstack-clash-protection", "", vars[var])
 
 from distutils.core import setup, Extension
 
index 9005fbe..23092fd 100644 (file)
@@ -109,7 +109,6 @@ static int strbuf_addv(struct strbuf *sb, const char *fmt, va_list ap)
                        return ret;
                }
                len = vsnprintf(sb->buf + sb->len, sb->alloc - sb->len, fmt, ap_saved);
-               va_end(ap_saved);
                if (len > strbuf_avail(sb)) {
                        pr_debug("this should not happen, your vsnprintf is broken");
                        va_end(ap_saved);
index 66a84d5..dca7dfa 100644 (file)
 #define EM_AARCH64     183  /* ARM 64 bit */
 #endif
 
+#ifndef ELF32_ST_VISIBILITY
+#define ELF32_ST_VISIBILITY(o) ((o) & 0x03)
+#endif
+
+/* For ELF64 the definitions are the same.  */
+#ifndef ELF64_ST_VISIBILITY
+#define ELF64_ST_VISIBILITY(o) ELF32_ST_VISIBILITY (o)
+#endif
+
+/* How to extract information held in the st_other field.  */
+#ifndef GELF_ST_VISIBILITY
+#define GELF_ST_VISIBILITY(val)        ELF64_ST_VISIBILITY (val)
+#endif
+
 typedef Elf64_Nhdr GElf_Nhdr;
 
 #ifdef HAVE_CPLUS_DEMANGLE_SUPPORT
@@ -87,6 +101,11 @@ static inline uint8_t elf_sym__type(const GElf_Sym *sym)
        return GELF_ST_TYPE(sym->st_info);
 }
 
+static inline uint8_t elf_sym__visibility(const GElf_Sym *sym)
+{
+       return GELF_ST_VISIBILITY(sym->st_other);
+}
+
 #ifndef STT_GNU_IFUNC
 #define STT_GNU_IFUNC 10
 #endif
@@ -111,7 +130,9 @@ static inline int elf_sym__is_label(const GElf_Sym *sym)
        return elf_sym__type(sym) == STT_NOTYPE &&
                sym->st_name != 0 &&
                sym->st_shndx != SHN_UNDEF &&
-               sym->st_shndx != SHN_ABS;
+               sym->st_shndx != SHN_ABS &&
+               elf_sym__visibility(sym) != STV_HIDDEN &&
+               elf_sym__visibility(sym) != STV_INTERNAL;
 }
 
 static bool elf_sym__filter(GElf_Sym *sym)
index 01f2c73..48efad6 100644 (file)
@@ -614,6 +614,7 @@ out:
 static bool symbol__is_idle(const char *name)
 {
        const char * const idle_symbols[] = {
+               "arch_cpu_idle",
                "cpu_idle",
                "cpu_startup_entry",
                "intel_idle",
index 741af20..3702cba 100644 (file)
 #include "debug.h"
 
 /*
- * Include definition of find_vdso_map() also used in perf-read-vdso.c for
+ * Include definition of find_map() also used in perf-read-vdso.c for
  * building perf-read-vdso32 and perf-read-vdsox32.
  */
-#include "find-vdso-map.c"
+#include "find-map.c"
 
 #define VDSO__TEMP_FILE_NAME "/tmp/perf-vdso.so-XXXXXX"
 
@@ -76,7 +76,7 @@ static char *get_file(struct vdso_file *vdso_file)
        if (vdso_file->found)
                return vdso_file->temp_file_name;
 
-       if (vdso_file->error || find_vdso_map(&start, &end))
+       if (vdso_file->error || find_map(&start, &end, VDSO__MAP_NAME))
                return NULL;
 
        size = end - start;
index e752384..2d4baf5 100644 (file)
@@ -18,8 +18,8 @@ ssize_t security_show(struct device *dev,
         * For the test version we need to poll the "hardware" in order
         * to get the updated status for unlock testing.
         */
-       nvdimm->sec.state = nvdimm_security_state(nvdimm, false);
-       nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, true);
+       nvdimm->sec.state = nvdimm_security_state(nvdimm, NVDIMM_USER);
+       nvdimm->sec.ext_state = nvdimm_security_state(nvdimm, NVDIMM_MASTER);
 
        switch (nvdimm->sec.state) {
        case NVDIMM_SECURITY_DISABLED:
index 1a2bd15..400ee81 100644 (file)
@@ -10,6 +10,7 @@ TARGETS += drivers/dma-buf
 TARGETS += efivarfs
 TARGETS += exec
 TARGETS += filesystems
+TARGETS += filesystems/binderfs
 TARGETS += firmware
 TARGETS += ftrace
 TARGETS += futex
index 4a97850..dd093bd 100644 (file)
@@ -28,3 +28,4 @@ flow_dissector_load
 test_netcnt
 test_section_names
 test_tcpnotify_user
+test_libbpf
index 73aa6d8..41ab7a3 100644 (file)
@@ -55,7 +55,10 @@ TEST_PROGS := test_kmod.sh \
        test_flow_dissector.sh \
        test_xdp_vlan.sh
 
-TEST_PROGS_EXTENDED := with_addr.sh
+TEST_PROGS_EXTENDED := with_addr.sh \
+       with_tunnels.sh \
+       tcp_client.py \
+       tcp_server.py
 
 # Compile but not part of 'make run_tests'
 TEST_GEN_PROGS_EXTENDED = test_libbpf_open test_sock_addr test_skb_cgroup_id_user \
index 315a44f..84fd6f1 100644 (file)
@@ -13,7 +13,7 @@ static inline unsigned int bpf_num_possible_cpus(void)
        unsigned int start, end, possible_cpus = 0;
        char buff[128];
        FILE *fp;
-       int n;
+       int len, n, i, j = 0;
 
        fp = fopen(fcpu, "r");
        if (!fp) {
@@ -21,17 +21,27 @@ static inline unsigned int bpf_num_possible_cpus(void)
                exit(1);
        }
 
-       while (fgets(buff, sizeof(buff), fp)) {
-               n = sscanf(buff, "%u-%u", &start, &end);
-               if (n == 0) {
-                       printf("Failed to retrieve # possible CPUs!\n");
-                       exit(1);
-               } else if (n == 1) {
-                       end = start;
+       if (!fgets(buff, sizeof(buff), fp)) {
+               printf("Failed to read %s!\n", fcpu);
+               exit(1);
+       }
+
+       len = strlen(buff);
+       for (i = 0; i <= len; i++) {
+               if (buff[i] == ',' || buff[i] == '\0') {
+                       buff[i] = '\0';
+                       n = sscanf(&buff[j], "%u-%u", &start, &end);
+                       if (n <= 0) {
+                               printf("Failed to retrieve # possible CPUs!\n");
+                               exit(1);
+                       } else if (n == 1) {
+                               end = start;
+                       }
+                       possible_cpus += end - start + 1;
+                       j = i + 1;
                }
-               possible_cpus = start == 0 ? end + 1 : 0;
-               break;
        }
+
        fclose(fp);
 
        return possible_cpus;
index cf16948..6692a40 100644 (file)
@@ -155,7 +155,7 @@ void cleanup_cgroup_environment(void)
  * This function creates a cgroup under the top level workdir and returns the
  * file descriptor. It is idempotent.
  *
- * On success, it returns the file descriptor. On failure it returns 0.
+ * On success, it returns the file descriptor. On failure it returns -1.
  * If there is a failure, it prints the error to stderr.
  */
 int create_and_get_cgroup(const char *path)
@@ -166,13 +166,13 @@ int create_and_get_cgroup(const char *path)
        format_cgroup_path(cgroup_path, path);
        if (mkdir(cgroup_path, 0777) && errno != EEXIST) {
                log_err("mkdiring cgroup %s .. %s", path, cgroup_path);
-               return 0;
+               return -1;
        }
 
        fd = open(cgroup_path, O_RDONLY);
        if (fd < 0) {
                log_err("Opening Cgroup");
-               return 0;
+               return -1;
        }
 
        return fd;
index 8bcd380..91420fa 100644 (file)
@@ -1881,13 +1881,12 @@ static struct btf_raw_test raw_tests[] = {
 },
 
 {
-       .descr = "func proto (CONST=>TYPEDEF=>FUNC_PROTO)",
+       .descr = "func proto (TYPEDEF=>FUNC_PROTO)",
        .raw_types = {
                BTF_TYPE_INT_ENC(0, BTF_INT_SIGNED, 0, 32, 4),  /* [1] */
                BTF_TYPE_INT_ENC(0, 0, 0, 32, 4),               /* [2] */
-               BTF_CONST_ENC(4),                               /* [3] */
-               BTF_TYPEDEF_ENC(NAME_TBD, 5),                   /* [4] */
-               BTF_FUNC_PROTO_ENC(0, 2),                       /* [5] */
+               BTF_TYPEDEF_ENC(NAME_TBD, 4),                   /* [3] */
+               BTF_FUNC_PROTO_ENC(0, 2),                       /* [4] */
                        BTF_FUNC_PROTO_ARG_ENC(0, 1),
                        BTF_FUNC_PROTO_ARG_ENC(0, 2),
                BTF_END_RAW,
@@ -1901,8 +1900,6 @@ static struct btf_raw_test raw_tests[] = {
        .key_type_id = 1,
        .value_type_id = 1,
        .max_entries = 4,
-       .btf_load_err = true,
-       .err_str = "Invalid type_id",
 },
 
 {
@@ -3526,6 +3523,8 @@ struct pprint_mapv {
                ENUM_TWO,
                ENUM_THREE,
        } aenum;
+       uint32_t ui32b;
+       uint32_t bits2c:2;
 };
 
 static struct btf_raw_test pprint_test_template[] = {
@@ -3568,7 +3567,7 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_ENUM_ENC(NAME_TBD, 2),
                BTF_ENUM_ENC(NAME_TBD, 3),
                /* struct pprint_mapv */                /* [16] */
-               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 8), 32),
+               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 0, 10), 40),
                BTF_MEMBER_ENC(NAME_TBD, 11, 0),        /* uint32_t ui32 */
                BTF_MEMBER_ENC(NAME_TBD, 10, 32),       /* uint16_t ui16 */
                BTF_MEMBER_ENC(NAME_TBD, 12, 64),       /* int32_t si32 */
@@ -3577,9 +3576,11 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_MEMBER_ENC(NAME_TBD, 6, 126),       /* unused_bits2b */
                BTF_MEMBER_ENC(0, 14, 128),             /* union (anon) */
                BTF_MEMBER_ENC(NAME_TBD, 15, 192),      /* aenum */
+               BTF_MEMBER_ENC(NAME_TBD, 11, 224),      /* uint32_t ui32b */
+               BTF_MEMBER_ENC(NAME_TBD, 6, 256),       /* bits2c */
                BTF_END_RAW,
        },
-       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum"),
+       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c"),
        .key_size = sizeof(unsigned int),
        .value_size = sizeof(struct pprint_mapv),
        .key_type_id = 3,       /* unsigned int */
@@ -3628,7 +3629,7 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_ENUM_ENC(NAME_TBD, 2),
                BTF_ENUM_ENC(NAME_TBD, 3),
                /* struct pprint_mapv */                /* [16] */
-               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 8), 32),
+               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 10), 40),
                BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 0)),  /* uint32_t ui32 */
                BTF_MEMBER_ENC(NAME_TBD, 10, BTF_MEMBER_OFFSET(0, 32)), /* uint16_t ui16 */
                BTF_MEMBER_ENC(NAME_TBD, 12, BTF_MEMBER_OFFSET(0, 64)), /* int32_t si32 */
@@ -3637,9 +3638,11 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_MEMBER_ENC(NAME_TBD, 6, BTF_MEMBER_OFFSET(2, 126)), /* unused_bits2b */
                BTF_MEMBER_ENC(0, 14, BTF_MEMBER_OFFSET(0, 128)),       /* union (anon) */
                BTF_MEMBER_ENC(NAME_TBD, 15, BTF_MEMBER_OFFSET(0, 192)),        /* aenum */
+               BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 224)),        /* uint32_t ui32b */
+               BTF_MEMBER_ENC(NAME_TBD, 6, BTF_MEMBER_OFFSET(2, 256)), /* bits2c */
                BTF_END_RAW,
        },
-       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum"),
+       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c"),
        .key_size = sizeof(unsigned int),
        .value_size = sizeof(struct pprint_mapv),
        .key_type_id = 3,       /* unsigned int */
@@ -3690,7 +3693,7 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_ENUM_ENC(NAME_TBD, 2),
                BTF_ENUM_ENC(NAME_TBD, 3),
                /* struct pprint_mapv */                /* [16] */
-               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 8), 32),
+               BTF_TYPE_ENC(NAME_TBD, BTF_INFO_ENC(BTF_KIND_STRUCT, 1, 10), 40),
                BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 0)),  /* uint32_t ui32 */
                BTF_MEMBER_ENC(NAME_TBD, 10, BTF_MEMBER_OFFSET(0, 32)), /* uint16_t ui16 */
                BTF_MEMBER_ENC(NAME_TBD, 12, BTF_MEMBER_OFFSET(0, 64)), /* int32_t si32 */
@@ -3699,13 +3702,15 @@ static struct btf_raw_test pprint_test_template[] = {
                BTF_MEMBER_ENC(NAME_TBD, 19, BTF_MEMBER_OFFSET(2, 126)),/* unused_bits2b */
                BTF_MEMBER_ENC(0, 14, BTF_MEMBER_OFFSET(0, 128)),       /* union (anon) */
                BTF_MEMBER_ENC(NAME_TBD, 15, BTF_MEMBER_OFFSET(0, 192)),        /* aenum */
+               BTF_MEMBER_ENC(NAME_TBD, 11, BTF_MEMBER_OFFSET(0, 224)),        /* uint32_t ui32b */
+               BTF_MEMBER_ENC(NAME_TBD, 17, BTF_MEMBER_OFFSET(2, 256)),        /* bits2c */
                /* typedef unsigned int ___int */       /* [17] */
                BTF_TYPEDEF_ENC(NAME_TBD, 18),
                BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_VOLATILE, 0, 0), 6),      /* [18] */
                BTF_TYPE_ENC(0, BTF_INFO_ENC(BTF_KIND_CONST, 0, 0), 15),        /* [19] */
                BTF_END_RAW,
        },
-       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0___int"),
+       BTF_STR_SEC("\0unsigned char\0unsigned short\0unsigned int\0int\0unsigned long long\0uint8_t\0uint16_t\0uint32_t\0int32_t\0uint64_t\0ui64\0ui8a\0ENUM_ZERO\0ENUM_ONE\0ENUM_TWO\0ENUM_THREE\0pprint_mapv\0ui32\0ui16\0si32\0unused_bits2a\0bits28\0unused_bits2b\0aenum\0ui32b\0bits2c\0___int"),
        .key_size = sizeof(unsigned int),
        .value_size = sizeof(struct pprint_mapv),
        .key_type_id = 3,       /* unsigned int */
@@ -3793,6 +3798,8 @@ static void set_pprint_mapv(struct pprint_mapv *v, uint32_t i,
                v->unused_bits2b = 3;
                v->ui64 = i;
                v->aenum = i & 0x03;
+               v->ui32b = 4;
+               v->bits2c = 1;
                v = (void *)v + rounded_value_size;
        }
 }
@@ -3955,7 +3962,8 @@ static int do_test_pprint(int test_num)
 
                        nexpected_line = snprintf(expected_line, sizeof(expected_line),
                                                  "%s%u: {%u,0,%d,0x%x,0x%x,0x%x,"
-                                                 "{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s}\n",
+                                                 "{%lu|[%u,%u,%u,%u,%u,%u,%u,%u]},%s,"
+                                                 "%u,0x%x}\n",
                                                  percpu_map ? "\tcpu" : "",
                                                  percpu_map ? cpu : next_key,
                                                  cmapv->ui32, cmapv->si32,
@@ -3967,7 +3975,9 @@ static int do_test_pprint(int test_num)
                                                  cmapv->ui8a[2], cmapv->ui8a[3],
                                                  cmapv->ui8a[4], cmapv->ui8a[5],
                                                  cmapv->ui8a[6], cmapv->ui8a[7],
-                                                 pprint_enum_str[cmapv->aenum]);
+                                                 pprint_enum_str[cmapv->aenum],
+                                                 cmapv->ui32b,
+                                                 cmapv->bits2c);
 
                        err = check_line(expected_line, nexpected_line,
                                         sizeof(expected_line), line);
index f448341..2fc4625 100644 (file)
@@ -81,7 +81,7 @@ int main(int argc, char **argv)
 
        /* Create a cgroup, get fd, and join it */
        cgroup_fd = create_and_get_cgroup(TEST_CGROUP);
-       if (!cgroup_fd) {
+       if (cgroup_fd < 0) {
                printf("Failed to create test cgroup\n");
                goto err;
        }
index 9c8b50b..76e4993 100644 (file)
@@ -43,7 +43,7 @@ int main(int argc, char **argv)
 
        /* Create a cgroup, get fd, and join it */
        cgroup_fd = create_and_get_cgroup(TEST_CGROUP);
-       if (!cgroup_fd) {
+       if (cgroup_fd < 0) {
                printf("Failed to create test cgroup\n");
                goto err;
        }
index 147e34c..02d7c87 100644 (file)
@@ -474,6 +474,16 @@ static void test_lpm_delete(void)
        assert(bpf_map_lookup_elem(map_fd, key, &value) == -1 &&
                errno == ENOENT);
 
+       key->prefixlen = 30; // unused prefix so far
+       inet_pton(AF_INET, "192.255.0.0", key->data);
+       assert(bpf_map_delete_elem(map_fd, key) == -1 &&
+               errno == ENOENT);
+
+       key->prefixlen = 16; // same prefix as the root node
+       inet_pton(AF_INET, "192.255.0.0", key->data);
+       assert(bpf_map_delete_elem(map_fd, key) == -1 &&
+               errno == ENOENT);
+
        /* assert initial lookup */
        key->prefixlen = 32;
        inet_pton(AF_INET, "192.168.0.1", key->data);
index 44ed7f2..c1da540 100644 (file)
@@ -65,7 +65,7 @@ int main(int argc, char **argv)
 
        /* Create a cgroup, get fd, and join it */
        cgroup_fd = create_and_get_cgroup(TEST_CGROUP);
-       if (!cgroup_fd) {
+       if (cgroup_fd < 0) {
                printf("Failed to create test cgroup\n");
                goto err;
        }
index 126fc62..25f0083 100644 (file)
@@ -1188,7 +1188,9 @@ static void test_stacktrace_build_id(void)
        int i, j;
        struct bpf_stack_build_id id_offs[PERF_MAX_STACK_DEPTH];
        int build_id_matches = 0;
+       int retry = 1;
 
+retry:
        err = bpf_prog_load(file, BPF_PROG_TYPE_TRACEPOINT, &obj, &prog_fd);
        if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
                goto out;
@@ -1301,6 +1303,19 @@ static void test_stacktrace_build_id(void)
                previous_key = key;
        } while (bpf_map_get_next_key(stackmap_fd, &previous_key, &key) == 0);
 
+       /* stack_map_get_build_id_offset() is racy and sometimes can return
+        * BPF_STACK_BUILD_ID_IP instead of BPF_STACK_BUILD_ID_VALID;
+        * try it one more time.
+        */
+       if (build_id_matches < 1 && retry--) {
+               ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
+               close(pmu_fd);
+               bpf_object__close(obj);
+               printf("%s:WARN:Didn't find expected build ID from the map, retrying\n",
+                      __func__);
+               goto retry;
+       }
+
        if (CHECK(build_id_matches < 1, "build id match",
                  "Didn't find expected build ID from the map\n"))
                goto disable_pmu;
@@ -1341,7 +1356,9 @@ static void test_stacktrace_build_id_nmi(void)
        int i, j;
        struct bpf_stack_build_id id_offs[PERF_MAX_STACK_DEPTH];
        int build_id_matches = 0;
+       int retry = 1;
 
+retry:
        err = bpf_prog_load(file, BPF_PROG_TYPE_PERF_EVENT, &obj, &prog_fd);
        if (CHECK(err, "prog_load", "err %d errno %d\n", err, errno))
                return;
@@ -1436,6 +1453,19 @@ static void test_stacktrace_build_id_nmi(void)
                previous_key = key;
        } while (bpf_map_get_next_key(stackmap_fd, &previous_key, &key) == 0);
 
+       /* stack_map_get_build_id_offset() is racy and sometimes can return
+        * BPF_STACK_BUILD_ID_IP instead of BPF_STACK_BUILD_ID_VALID;
+        * try it one more time.
+        */
+       if (build_id_matches < 1 && retry--) {
+               ioctl(pmu_fd, PERF_EVENT_IOC_DISABLE);
+               close(pmu_fd);
+               bpf_object__close(obj);
+               printf("%s:WARN:Didn't find expected build ID from the map, retrying\n",
+                      __func__);
+               goto retry;
+       }
+
        if (CHECK(build_id_matches < 1, "build id match",
                  "Didn't find expected build ID from the map\n"))
                goto disable_pmu;
index c121cc5..9220747 100644 (file)
@@ -164,7 +164,7 @@ int main(int argc, char **argv)
                goto err;
 
        cgfd = create_and_get_cgroup(CGROUP_PATH);
-       if (!cgfd)
+       if (cgfd < 0)
                goto err;
 
        if (join_cgroup(CGROUP_PATH))
index b8ebe2f..561ffb6 100644 (file)
@@ -458,7 +458,7 @@ int main(int argc, char **argv)
                goto err;
 
        cgfd = create_and_get_cgroup(CG_PATH);
-       if (!cgfd)
+       if (cgfd < 0)
                goto err;
 
        if (join_cgroup(CG_PATH))
index 73b7493..3f110ea 100644 (file)
@@ -44,6 +44,7 @@
 #define SERV6_V4MAPPED_IP      "::ffff:192.168.0.4"
 #define SRC6_IP                        "::1"
 #define SRC6_REWRITE_IP                "::6"
+#define WILDCARD6_IP           "::"
 #define SERV6_PORT             6060
 #define SERV6_REWRITE_PORT     6666
 
@@ -85,12 +86,14 @@ static int bind4_prog_load(const struct sock_addr_test *test);
 static int bind6_prog_load(const struct sock_addr_test *test);
 static int connect4_prog_load(const struct sock_addr_test *test);
 static int connect6_prog_load(const struct sock_addr_test *test);
+static int sendmsg_allow_prog_load(const struct sock_addr_test *test);
 static int sendmsg_deny_prog_load(const struct sock_addr_test *test);
 static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test);
 static int sendmsg4_rw_c_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_asm_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test);
 static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test);
+static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test);
 
 static struct sock_addr_test tests[] = {
        /* bind */
@@ -462,6 +465,34 @@ static struct sock_addr_test tests[] = {
                SRC6_REWRITE_IP,
                SYSCALL_ENOTSUPP,
        },
+       {
+               "sendmsg6: set dst IP = [::] (BSD'ism)",
+               sendmsg6_rw_wildcard_prog_load,
+               BPF_CGROUP_UDP6_SENDMSG,
+               BPF_CGROUP_UDP6_SENDMSG,
+               AF_INET6,
+               SOCK_DGRAM,
+               SERV6_IP,
+               SERV6_PORT,
+               SERV6_REWRITE_IP,
+               SERV6_REWRITE_PORT,
+               SRC6_REWRITE_IP,
+               SUCCESS,
+       },
+       {
+               "sendmsg6: preserve dst IP = [::] (BSD'ism)",
+               sendmsg_allow_prog_load,
+               BPF_CGROUP_UDP6_SENDMSG,
+               BPF_CGROUP_UDP6_SENDMSG,
+               AF_INET6,
+               SOCK_DGRAM,
+               WILDCARD6_IP,
+               SERV6_PORT,
+               SERV6_REWRITE_IP,
+               SERV6_PORT,
+               SRC6_IP,
+               SUCCESS,
+       },
        {
                "sendmsg6: deny call",
                sendmsg_deny_prog_load,
@@ -734,16 +765,27 @@ static int connect6_prog_load(const struct sock_addr_test *test)
        return load_path(test, CONNECT6_PROG_PATH);
 }
 
-static int sendmsg_deny_prog_load(const struct sock_addr_test *test)
+static int sendmsg_ret_only_prog_load(const struct sock_addr_test *test,
+                                     int32_t rc)
 {
        struct bpf_insn insns[] = {
-               /* return 0 */
-               BPF_MOV64_IMM(BPF_REG_0, 0),
+               /* return rc */
+               BPF_MOV64_IMM(BPF_REG_0, rc),
                BPF_EXIT_INSN(),
        };
        return load_insns(test, insns, sizeof(insns) / sizeof(struct bpf_insn));
 }
 
+static int sendmsg_allow_prog_load(const struct sock_addr_test *test)
+{
+       return sendmsg_ret_only_prog_load(test, /*rc*/ 1);
+}
+
+static int sendmsg_deny_prog_load(const struct sock_addr_test *test)
+{
+       return sendmsg_ret_only_prog_load(test, /*rc*/ 0);
+}
+
 static int sendmsg4_rw_asm_prog_load(const struct sock_addr_test *test)
 {
        struct sockaddr_in dst4_rw_addr;
@@ -864,6 +906,11 @@ static int sendmsg6_rw_v4mapped_prog_load(const struct sock_addr_test *test)
        return sendmsg6_rw_dst_asm_prog_load(test, SERV6_V4MAPPED_IP);
 }
 
+static int sendmsg6_rw_wildcard_prog_load(const struct sock_addr_test *test)
+{
+       return sendmsg6_rw_dst_asm_prog_load(test, WILDCARD6_IP);
+}
+
 static int sendmsg6_rw_c_prog_load(const struct sock_addr_test *test)
 {
        return load_path(test, SENDMSG6_PROG_PATH);
@@ -1395,7 +1442,7 @@ int main(int argc, char **argv)
                goto err;
 
        cgfd = create_and_get_cgroup(CG_PATH);
-       if (!cgfd)
+       if (cgfd < 0)
                goto err;
 
        if (join_cgroup(CG_PATH))
index b6c2c60..fc7832e 100644 (file)
@@ -202,7 +202,7 @@ int main(int argc, char **argv)
                goto err;
 
        cgfd = create_and_get_cgroup(CG_PATH);
-       if (!cgfd)
+       if (cgfd < 0)
                goto err;
 
        if (join_cgroup(CG_PATH))
index e6eebda..716b4e3 100644 (file)
@@ -103,7 +103,7 @@ int main(int argc, char **argv)
                goto err;
 
        cg_fd = create_and_get_cgroup(cg_path);
-       if (!cg_fd)
+       if (cg_fd < 0)
                goto err;
 
        if (join_cgroup(cg_path))
index ff3c452..4e43537 100644 (file)
@@ -115,7 +115,7 @@ int main(int argc, char **argv)
                goto err;
 
        cg_fd = create_and_get_cgroup(cg_path);
-       if (!cg_fd)
+       if (cg_fd < 0)
                goto err;
 
        if (join_cgroup(cg_path))
index 10d4444..2fd90d4 100644 (file)
@@ -6933,6 +6933,126 @@ static struct bpf_test tests[] = {
                .result = ACCEPT,
                .retval = 1,
        },
+       {
+               "map access: mixing value pointer and scalar, 1",
+               .insns = {
+                       // load map value pointer into r0 and r2
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
+                       BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -16),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_FP, -16, 0),
+                       BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+                       BPF_EXIT_INSN(),
+                       // load some number from the map into r1
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 3),
+                       // branch A
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0),
+                       BPF_JMP_A(2),
+                       // branch B
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100000),
+                       // common instruction
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_3),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
+                       // branch A
+                       BPF_JMP_A(4),
+                       // branch B
+                       BPF_MOV64_IMM(BPF_REG_0, 0x13371337),
+                       // verifier follows fall-through
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0x100000, 2),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+                       // fake-dead code; targeted from branch A to
+                       // prevent dead code sanitization
+                       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 1 },
+               .result = ACCEPT,
+               .result_unpriv = REJECT,
+               .errstr_unpriv = "R2 tried to add from different pointers or scalars",
+               .retval = 0,
+       },
+       {
+               "map access: mixing value pointer and scalar, 2",
+               .insns = {
+                       // load map value pointer into r0 and r2
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
+                       BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -16),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_FP, -16, 0),
+                       BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+                       BPF_EXIT_INSN(),
+                       // load some number from the map into r1
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
+                       // branch A
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100000),
+                       BPF_JMP_A(2),
+                       // branch B
+                       BPF_MOV64_REG(BPF_REG_2, BPF_REG_0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0),
+                       // common instruction
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_3),
+                       // depending on r1, branch:
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_1, 0, 1),
+                       // branch A
+                       BPF_JMP_A(4),
+                       // branch B
+                       BPF_MOV64_IMM(BPF_REG_0, 0x13371337),
+                       // verifier follows fall-through
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_2, 0x100000, 2),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+                       // fake-dead code; targeted from branch A to
+                       // prevent dead code sanitization
+                       BPF_LDX_MEM(BPF_B, BPF_REG_0, BPF_REG_0, 0),
+                       BPF_MOV64_IMM(BPF_REG_0, 0),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 1 },
+               .result = ACCEPT,
+               .result_unpriv = REJECT,
+               .errstr_unpriv = "R2 tried to add from different maps or paths",
+               .retval = 0,
+       },
+       {
+               "sanitation: alu with different scalars",
+               .insns = {
+                       BPF_MOV64_IMM(BPF_REG_0, 1),
+                       BPF_LD_MAP_FD(BPF_REG_ARG1, 0),
+                       BPF_MOV64_REG(BPF_REG_ARG2, BPF_REG_FP),
+                       BPF_ALU64_IMM(BPF_ADD, BPF_REG_ARG2, -16),
+                       BPF_ST_MEM(BPF_DW, BPF_REG_FP, -16, 0),
+                       BPF_EMIT_CALL(BPF_FUNC_map_lookup_elem),
+                       BPF_JMP_IMM(BPF_JNE, BPF_REG_0, 0, 1),
+                       BPF_EXIT_INSN(),
+                       BPF_LDX_MEM(BPF_B, BPF_REG_1, BPF_REG_0, 0),
+                       BPF_JMP_IMM(BPF_JEQ, BPF_REG_1, 0, 3),
+                       BPF_MOV64_IMM(BPF_REG_2, 0),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100000),
+                       BPF_JMP_A(2),
+                       BPF_MOV64_IMM(BPF_REG_2, 42),
+                       BPF_MOV64_IMM(BPF_REG_3, 0x100001),
+                       BPF_ALU64_REG(BPF_ADD, BPF_REG_2, BPF_REG_3),
+                       BPF_MOV64_REG(BPF_REG_0, BPF_REG_2),
+                       BPF_EXIT_INSN(),
+               },
+               .fixup_map_array_48b = { 1 },
+               .result = ACCEPT,
+               .retval = 0x100000,
+       },
        {
                "map access: value_ptr += known scalar, upper oob arith, test 1",
                .insns = {
index bab13dd..0d26b5e 100755 (executable)
@@ -37,6 +37,10 @@ prerequisite()
                exit $ksft_skip
        fi
 
+       present_cpus=`cat $SYSFS/devices/system/cpu/present`
+       present_max=${present_cpus##*-}
+       echo "present_cpus = $present_cpus present_max = $present_max"
+
        echo -e "\t Cpus in online state: $online_cpus"
 
        offline_cpus=`cat $SYSFS/devices/system/cpu/offline`
@@ -151,6 +155,8 @@ online_cpus=0
 online_max=0
 offline_cpus=0
 offline_max=0
+present_cpus=0
+present_max=0
 
 while getopts e:ahp: opt; do
        case $opt in
@@ -190,9 +196,10 @@ if [ $allcpus -eq 0 ]; then
        online_cpu_expect_success $online_max
 
        if [[ $offline_cpus -gt 0 ]]; then
-               echo -e "\t offline to online to offline: cpu $offline_max"
-               online_cpu_expect_success $offline_max
-               offline_cpu_expect_success $offline_max
+               echo -e "\t offline to online to offline: cpu $present_max"
+               online_cpu_expect_success $present_max
+               offline_cpu_expect_success $present_max
+               online_cpu $present_max
        fi
        exit 0
 else
index 94fdbf2..c4cf6e6 100755 (executable)
@@ -25,6 +25,7 @@ ALL_TESTS="
        lag_unlink_slaves_test
        lag_dev_deletion_test
        vlan_interface_uppers_test
+       bridge_extern_learn_test
        devlink_reload_test
 "
 NUM_NETIFS=2
@@ -541,6 +542,25 @@ vlan_interface_uppers_test()
        ip link del dev br0
 }
 
+bridge_extern_learn_test()
+{
+       # Test that externally learned entries added from user space are
+       # marked as offloaded
+       RET=0
+
+       ip link add name br0 type bridge
+       ip link set dev $swp1 master br0
+
+       bridge fdb add de:ad:be:ef:13:37 dev $swp1 master extern_learn
+
+       bridge fdb show brport $swp1 | grep de:ad:be:ef:13:37 | grep -q offload
+       check_err $? "fdb entry not marked as offloaded when should"
+
+       log_test "externally learned fdb entry"
+
+       ip link del dev br0
+}
+
 devlink_reload_test()
 {
        # Test that after executing all the above configuration tests, a
index dcf9f4e..ae6146e 100755 (executable)
@@ -847,6 +847,24 @@ sanitization_vlan_aware_test()
 
        log_test "vlan-aware - failed enslavement to vlan-aware bridge"
 
+       bridge vlan del vid 10 dev vxlan20
+       bridge vlan add vid 20 dev vxlan20 pvid untagged
+
+       # Test that offloading of an unsupported tunnel fails when it is
+       # triggered by addition of VLAN to a local port
+       RET=0
+
+       # TOS must be set to inherit
+       ip link set dev vxlan10 type vxlan tos 42
+
+       ip link set dev $swp1 master br0
+       bridge vlan add vid 10 dev $swp1 &> /dev/null
+       check_fail $?
+
+       log_test "vlan-aware - failed vlan addition to a local port"
+
+       ip link set dev vxlan10 type vxlan tos inherit
+
        ip link del dev vxlan20
        ip link del dev vxlan10
        ip link del dev br0
diff --git a/tools/testing/selftests/filesystems/binderfs/.gitignore b/tools/testing/selftests/filesystems/binderfs/.gitignore
new file mode 100644 (file)
index 0000000..8a5d9bf
--- /dev/null
@@ -0,0 +1 @@
+binderfs_test
diff --git a/tools/testing/selftests/filesystems/binderfs/Makefile b/tools/testing/selftests/filesystems/binderfs/Makefile
new file mode 100644 (file)
index 0000000..58cb659
--- /dev/null
@@ -0,0 +1,6 @@
+# SPDX-License-Identifier: GPL-2.0
+
+CFLAGS += -I../../../../../usr/include/
+TEST_GEN_PROGS := binderfs_test
+
+include ../../lib.mk
diff --git a/tools/testing/selftests/filesystems/binderfs/binderfs_test.c b/tools/testing/selftests/filesystems/binderfs/binderfs_test.c
new file mode 100644 (file)
index 0000000..8c2ed96
--- /dev/null
@@ -0,0 +1,275 @@
+// SPDX-License-Identifier: GPL-2.0
+
+#define _GNU_SOURCE
+#include <errno.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/mount.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <linux/android/binder.h>
+#include <linux/android/binderfs.h>
+#include "../../kselftest.h"
+
+static ssize_t write_nointr(int fd, const void *buf, size_t count)
+{
+       ssize_t ret;
+again:
+       ret = write(fd, buf, count);
+       if (ret < 0 && errno == EINTR)
+               goto again;
+
+       return ret;
+}
+
+static void write_to_file(const char *filename, const void *buf, size_t count,
+                         int allowed_errno)
+{
+       int fd, saved_errno;
+       ssize_t ret;
+
+       fd = open(filename, O_WRONLY | O_CLOEXEC);
+       if (fd < 0)
+               ksft_exit_fail_msg("%s - Failed to open file %s\n",
+                                  strerror(errno), filename);
+
+       ret = write_nointr(fd, buf, count);
+       if (ret < 0) {
+               if (allowed_errno && (errno == allowed_errno)) {
+                       close(fd);
+                       return;
+               }
+
+               goto on_error;
+       }
+
+       if ((size_t)ret != count)
+               goto on_error;
+
+       close(fd);
+       return;
+
+on_error:
+       saved_errno = errno;
+       close(fd);
+       errno = saved_errno;
+
+       if (ret < 0)
+               ksft_exit_fail_msg("%s - Failed to write to file %s\n",
+                                  strerror(errno), filename);
+
+       ksft_exit_fail_msg("Failed to write to file %s\n", filename);
+}
+
+static void change_to_userns(void)
+{
+       int ret;
+       uid_t uid;
+       gid_t gid;
+       /* {g,u}id_map files only allow a max of 4096 bytes written to them */
+       char idmap[4096];
+
+       uid = getuid();
+       gid = getgid();
+
+       ret = unshare(CLONE_NEWUSER);
+       if (ret < 0)
+               ksft_exit_fail_msg("%s - Failed to unshare user namespace\n",
+                                  strerror(errno));
+
+       write_to_file("/proc/self/setgroups", "deny", strlen("deny"), ENOENT);
+
+       ret = snprintf(idmap, sizeof(idmap), "0 %d 1", uid);
+       if (ret < 0 || (size_t)ret >= sizeof(idmap))
+               ksft_exit_fail_msg("%s - Failed to prepare uid mapping\n",
+                                  strerror(errno));
+
+       write_to_file("/proc/self/uid_map", idmap, strlen(idmap), 0);
+
+       ret = snprintf(idmap, sizeof(idmap), "0 %d 1", gid);
+       if (ret < 0 || (size_t)ret >= sizeof(idmap))
+               ksft_exit_fail_msg("%s - Failed to prepare uid mapping\n",
+                                  strerror(errno));
+
+       write_to_file("/proc/self/gid_map", idmap, strlen(idmap), 0);
+
+       ret = setgid(0);
+       if (ret)
+               ksft_exit_fail_msg("%s - Failed to setgid(0)\n",
+                                  strerror(errno));
+
+       ret = setuid(0);
+       if (ret)
+               ksft_exit_fail_msg("%s - Failed to setgid(0)\n",
+                                  strerror(errno));
+}
+
+static void change_to_mountns(void)
+{
+       int ret;
+
+       ret = unshare(CLONE_NEWNS);
+       if (ret < 0)
+               ksft_exit_fail_msg("%s - Failed to unshare mount namespace\n",
+                                  strerror(errno));
+
+       ret = mount(NULL, "/", NULL, MS_REC | MS_PRIVATE, 0);
+       if (ret < 0)
+               ksft_exit_fail_msg("%s - Failed to mount / as private\n",
+                                  strerror(errno));
+}
+
+static void rmdir_protect_errno(const char *dir)
+{
+       int saved_errno = errno;
+       (void)rmdir(dir);
+       errno = saved_errno;
+}
+
+static void __do_binderfs_test(void)
+{
+       int fd, ret, saved_errno;
+       size_t len;
+       ssize_t wret;
+       bool keep = false;
+       struct binderfs_device device = { 0 };
+       struct binder_version version = { 0 };
+
+       change_to_mountns();
+
+       ret = mkdir("/dev/binderfs", 0755);
+       if (ret < 0) {
+               if (errno != EEXIST)
+                       ksft_exit_fail_msg(
+                               "%s - Failed to create binderfs mountpoint\n",
+                               strerror(errno));
+
+               keep = true;
+       }
+
+       ret = mount(NULL, "/dev/binderfs", "binder", 0, 0);
+       if (ret < 0) {
+               if (errno != ENODEV)
+                       ksft_exit_fail_msg("%s - Failed to mount binderfs\n",
+                                          strerror(errno));
+
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_skip(
+                       "The Android binderfs filesystem is not available\n");
+       }
+
+       /* binderfs mount test passed */
+       ksft_inc_pass_cnt();
+
+       memcpy(device.name, "my-binder", strlen("my-binder"));
+
+       fd = open("/dev/binderfs/binder-control", O_RDONLY | O_CLOEXEC);
+       if (fd < 0)
+               ksft_exit_fail_msg(
+                       "%s - Failed to open binder-control device\n",
+                       strerror(errno));
+
+       ret = ioctl(fd, BINDER_CTL_ADD, &device);
+       saved_errno = errno;
+       close(fd);
+       errno = saved_errno;
+       if (ret < 0) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg(
+                       "%s - Failed to allocate new binder device\n",
+                       strerror(errno));
+       }
+
+       ksft_print_msg(
+               "Allocated new binder device with major %d, minor %d, and name %s\n",
+               device.major, device.minor, device.name);
+
+       /* binder device allocation test passed */
+       ksft_inc_pass_cnt();
+
+       fd = open("/dev/binderfs/my-binder", O_CLOEXEC | O_RDONLY);
+       if (fd < 0) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg("%s - Failed to open my-binder device\n",
+                                  strerror(errno));
+       }
+
+       ret = ioctl(fd, BINDER_VERSION, &version);
+       saved_errno = errno;
+       close(fd);
+       errno = saved_errno;
+       if (ret < 0) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg(
+                       "%s - Failed to open perform BINDER_VERSION request\n",
+                       strerror(errno));
+       }
+
+       ksft_print_msg("Detected binder version: %d\n",
+                      version.protocol_version);
+
+       /* binder transaction with binderfs binder device passed */
+       ksft_inc_pass_cnt();
+
+       ret = unlink("/dev/binderfs/my-binder");
+       if (ret < 0) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg("%s - Failed to delete binder device\n",
+                                  strerror(errno));
+       }
+
+       /* binder device removal passed */
+       ksft_inc_pass_cnt();
+
+       ret = unlink("/dev/binderfs/binder-control");
+       if (!ret) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg("Managed to delete binder-control device\n");
+       } else if (errno != EPERM) {
+               keep ? : rmdir_protect_errno("/dev/binderfs");
+               ksft_exit_fail_msg(
+                       "%s - Failed to delete binder-control device but exited with unexpected error code\n",
+                       strerror(errno));
+       }
+
+       /* binder-control device removal failed as expected */
+       ksft_inc_xfail_cnt();
+
+on_error:
+       ret = umount2("/dev/binderfs", MNT_DETACH);
+       keep ?: rmdir_protect_errno("/dev/binderfs");
+       if (ret < 0)
+               ksft_exit_fail_msg("%s - Failed to unmount binderfs\n",
+                                  strerror(errno));
+
+       /* binderfs unmount test passed */
+       ksft_inc_pass_cnt();
+}
+
+static void binderfs_test_privileged()
+{
+       if (geteuid() != 0)
+               ksft_print_msg(
+                       "Tests are not run as root. Skipping privileged tests\n");
+       else
+               __do_binderfs_test();
+}
+
+static void binderfs_test_unprivileged()
+{
+       change_to_userns();
+       __do_binderfs_test();
+}
+
+int main(int argc, char *argv[])
+{
+       binderfs_test_privileged();
+       binderfs_test_unprivileged();
+       ksft_exit_pass();
+}
diff --git a/tools/testing/selftests/filesystems/binderfs/config b/tools/testing/selftests/filesystems/binderfs/config
new file mode 100644 (file)
index 0000000..02dd6cc
--- /dev/null
@@ -0,0 +1,3 @@
+CONFIG_ANDROID=y
+CONFIG_ANDROID_BINDERFS=y
+CONFIG_ANDROID_BINDER_IPC=y
index f8d468f..aaa1e9f 100644 (file)
@@ -37,7 +37,7 @@ static int get_debugfs(char **path)
        struct libmnt_table *tb;
        struct libmnt_iter *itr = NULL;
        struct libmnt_fs *fs;
-       int found = 0;
+       int found = 0, ret;
 
        cxt = mnt_new_context();
        if (!cxt)
@@ -58,8 +58,11 @@ static int get_debugfs(char **path)
                        break;
                }
        }
-       if (found)
-               asprintf(path, "%s/gpio", mnt_fs_get_target(fs));
+       if (found) {
+               ret = asprintf(path, "%s/gpio", mnt_fs_get_target(fs));
+               if (ret < 0)
+                       err(EXIT_FAILURE, "failed to format string");
+       }
 
        mnt_free_iter(itr);
        mnt_free_context(cxt);
index f4ba8eb..ad06489 100644 (file)
@@ -1,5 +1,7 @@
 # SPDX-License-Identifier: GPL-2.0
 TEST_PROGS := ir_loopback.sh
 TEST_GEN_PROGS_EXTENDED := ir_loopback
+APIDIR := ../../../include/uapi
+CFLAGS += -Wall -O2 -I$(APIDIR)
 
 include ../lib.mk
index 23022e9..b52cfde 100644 (file)
@@ -571,7 +571,7 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
         * already exist.
         */
        region = (struct userspace_mem_region *) userspace_mem_region_find(
-               vm, guest_paddr, guest_paddr + npages * vm->page_size);
+               vm, guest_paddr, (guest_paddr + npages * vm->page_size) - 1);
        if (region != NULL)
                TEST_ASSERT(false, "overlapping userspace_mem_region already "
                        "exists\n"
@@ -587,15 +587,10 @@ void vm_userspace_mem_region_add(struct kvm_vm *vm,
                region = region->next) {
                if (region->region.slot == slot)
                        break;
-               if ((guest_paddr <= (region->region.guest_phys_addr
-                               + region->region.memory_size))
-                       && ((guest_paddr + npages * vm->page_size)
-                               >= region->region.guest_phys_addr))
-                       break;
        }
        if (region != NULL)
                TEST_ASSERT(false, "A mem region with the requested slot "
-                       "or overlapping physical memory range already exists.\n"
+                       "already exists.\n"
                        "  requested slot: %u paddr: 0x%lx npages: 0x%lx\n"
                        "  existing slot: %u paddr: 0x%lx size: 0x%lx",
                        slot, guest_paddr, npages,
index ea3c73e..c49c2a2 100644 (file)
@@ -103,6 +103,12 @@ int main(int argc, char *argv[])
 
        vcpu_ioctl(vm, VCPU_ID, KVM_ENABLE_CAP, &enable_evmcs_cap);
 
+       /* KVM should return supported EVMCS version range */
+       TEST_ASSERT(((evmcs_ver >> 8) >= (evmcs_ver & 0xff)) &&
+                   (evmcs_ver & 0xff) > 0,
+                   "Incorrect EVMCS version range: %x:%x\n",
+                   evmcs_ver & 0xff, evmcs_ver >> 8);
+
        run = vcpu_state(vm, VCPU_ID);
 
        vcpu_regs_get(vm, VCPU_ID, &regs1);
index f8f3e90..1e6d14d 100644 (file)
@@ -21,6 +21,6 @@ TEST_GEN_PROGS += reuseport_dualstack reuseaddr_conflict tls
 KSFT_KHDR_INSTALL := 1
 include ../lib.mk
 
-$(OUTPUT)/reuseport_bpf_numa: LDFLAGS += -lnuma
+$(OUTPUT)/reuseport_bpf_numa: LDLIBS += -lnuma
 $(OUTPUT)/tcp_mmap: LDFLAGS += -lpthread
 $(OUTPUT)/tcp_inq: LDFLAGS += -lpthread
index 802b4af..1080ff5 100755 (executable)
@@ -388,6 +388,7 @@ fib_carrier_unicast_test()
 
        set -e
        $IP link set dev dummy0 carrier off
+       sleep 1
        set +e
 
        echo "    Carrier down"
index d8313d0..b90dff8 100755 (executable)
@@ -1,7 +1,7 @@
 #!/bin/bash
 # SPDX-License-Identifier: GPL-2.0
 
-ALL_TESTS="ping_ipv4 ping_ipv6 learning flooding"
+ALL_TESTS="ping_ipv4 ping_ipv6 learning flooding vlan_deletion extern_learn"
 NUM_NETIFS=4
 CHECK_TC="yes"
 source lib.sh
@@ -96,6 +96,51 @@ flooding()
        flood_test $swp2 $h1 $h2
 }
 
+vlan_deletion()
+{
+       # Test that the deletion of a VLAN on a bridge port does not affect
+       # the PVID VLAN
+       log_info "Add and delete a VLAN on bridge port $swp1"
+
+       bridge vlan add vid 10 dev $swp1
+       bridge vlan del vid 10 dev $swp1
+
+       ping_ipv4
+       ping_ipv6
+}
+
+extern_learn()
+{
+       local mac=de:ad:be:ef:13:37
+       local ageing_time
+
+       # Test that externally learned FDB entries can roam, but not age out
+       RET=0
+
+       bridge fdb add de:ad:be:ef:13:37 dev $swp1 master extern_learn vlan 1
+
+       bridge fdb show brport $swp1 | grep -q de:ad:be:ef:13:37
+       check_err $? "Did not find FDB entry when should"
+
+       # Wait for 10 seconds after the ageing time to make sure the FDB entry
+       # was not aged out
+       ageing_time=$(bridge_ageing_time_get br0)
+       sleep $((ageing_time + 10))
+
+       bridge fdb show brport $swp1 | grep -q de:ad:be:ef:13:37
+       check_err $? "FDB entry was aged out when should not"
+
+       $MZ $h2 -c 1 -p 64 -a $mac -t ip -q
+
+       bridge fdb show brport $swp2 | grep -q de:ad:be:ef:13:37
+       check_err $? "FDB entry did not roam when should"
+
+       log_test "Externally learned FDB entry - ageing & roaming"
+
+       bridge fdb del de:ad:be:ef:13:37 dev $swp2 master vlan 1 &> /dev/null
+       bridge fdb del de:ad:be:ef:13:37 dev $swp1 master vlan 1 &> /dev/null
+}
+
 trap cleanup EXIT
 
 setup_prepare
index 56cef3b..bb10e33 100755 (executable)
@@ -629,7 +629,7 @@ __test_ecn_decap()
        RET=0
 
        tc filter add dev $h1 ingress pref 77 prot ip \
-               flower ip_tos $decapped_tos action pass
+               flower ip_tos $decapped_tos action drop
        sleep 1
        vxlan_encapped_ping_test v2 v1 192.0.2.17 \
                                 $orig_inner_tos $orig_outer_tos \
index 61ae278..5d56cc0 100644 (file)
@@ -203,6 +203,7 @@ static void send_udp_frags(int fd_raw, struct sockaddr *addr,
 {
        struct ip *iphdr = (struct ip *)ip_frame;
        struct ip6_hdr *ip6hdr = (struct ip6_hdr *)ip_frame;
+       const bool ipv4 = !ipv6;
        int res;
        int offset;
        int frag_len;
@@ -239,19 +240,53 @@ static void send_udp_frags(int fd_raw, struct sockaddr *addr,
                iphdr->ip_sum = 0;
        }
 
+       /* Occasionally test in-order fragments. */
+       if (!cfg_overlap && (rand() % 100 < 15)) {
+               offset = 0;
+               while (offset < (UDP_HLEN + payload_len)) {
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
+                       offset += max_frag_len;
+               }
+               return;
+       }
+
+       /* Occasionally test IPv4 "runs" (see net/ipv4/ip_fragment.c) */
+       if (ipv4 && !cfg_overlap && (rand() % 100 < 20) &&
+                       (payload_len > 9 * max_frag_len)) {
+               offset = 6 * max_frag_len;
+               while (offset < (UDP_HLEN + payload_len)) {
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
+                       offset += max_frag_len;
+               }
+               offset = 3 * max_frag_len;
+               while (offset < 6 * max_frag_len) {
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
+                       offset += max_frag_len;
+               }
+               offset = 0;
+               while (offset < 3 * max_frag_len) {
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
+                       offset += max_frag_len;
+               }
+               return;
+       }
+
        /* Odd fragments. */
        offset = max_frag_len;
        while (offset < (UDP_HLEN + payload_len)) {
                send_fragment(fd_raw, addr, alen, offset, ipv6);
+               /* IPv4 ignores duplicates, so randomly send a duplicate. */
+               if (ipv4 && (1 == rand() % 100))
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
                offset += 2 * max_frag_len;
        }
 
        if (cfg_overlap) {
                /* Send an extra random fragment. */
-               offset = rand() % (UDP_HLEN + payload_len - 1);
-               /* sendto() returns EINVAL if offset + frag_len is too small. */
                if (ipv6) {
                        struct ip6_frag *fraghdr = (struct ip6_frag *)(ip_frame + IP6_HLEN);
+                       /* sendto() returns EINVAL if offset + frag_len is too small. */
+                       offset = rand() % (UDP_HLEN + payload_len - 1);
                        frag_len = max_frag_len + rand() % 256;
                        /* In IPv6 if !!(frag_len % 8), the fragment is dropped. */
                        frag_len &= ~0x7;
@@ -259,13 +294,29 @@ static void send_udp_frags(int fd_raw, struct sockaddr *addr,
                        ip6hdr->ip6_plen = htons(frag_len);
                        frag_len += IP6_HLEN;
                } else {
-                       frag_len = IP4_HLEN + UDP_HLEN + rand() % 256;
+                       /* In IPv4, duplicates and some fragments completely inside
+                        * previously sent fragments are dropped/ignored. So
+                        * random offset and frag_len can result in a dropped
+                        * fragment instead of a dropped queue/packet. So we
+                        * hard-code offset and frag_len.
+                        *
+                        * See ade446403bfb ("net: ipv4: do not handle duplicate
+                        * fragments as overlapping").
+                        */
+                       if (max_frag_len * 4 < payload_len || max_frag_len < 16) {
+                               /* not enough payload to play with random offset and frag_len. */
+                               offset = 8;
+                               frag_len = IP4_HLEN + UDP_HLEN + max_frag_len;
+                       } else {
+                               offset = rand() % (payload_len / 2);
+                               frag_len = 2 * max_frag_len + 1 + rand() % 256;
+                       }
                        iphdr->ip_off = htons(offset / 8 | IP4_MF);
                        iphdr->ip_len = htons(frag_len);
                }
                res = sendto(fd_raw, ip_frame, frag_len, 0, addr, alen);
                if (res < 0)
-                       error(1, errno, "sendto overlap");
+                       error(1, errno, "sendto overlap: %d", frag_len);
                if (res != frag_len)
                        error(1, 0, "sendto overlap: %d vs %d", (int)res, frag_len);
                frag_counter++;
@@ -275,6 +326,9 @@ static void send_udp_frags(int fd_raw, struct sockaddr *addr,
        offset = 0;
        while (offset < (UDP_HLEN + payload_len)) {
                send_fragment(fd_raw, addr, alen, offset, ipv6);
+               /* IPv4 ignores duplicates, so randomly send a duplicate. */
+               if (ipv4 && (1 == rand() % 100))
+                       send_fragment(fd_raw, addr, alen, offset, ipv6);
                offset += 2 * max_frag_len;
        }
 }
@@ -282,7 +336,11 @@ static void send_udp_frags(int fd_raw, struct sockaddr *addr,
 static void run_test(struct sockaddr *addr, socklen_t alen, bool ipv6)
 {
        int fd_tx_raw, fd_rx_udp;
-       struct timeval tv = { .tv_sec = 0, .tv_usec = 10 * 1000 };
+       /* Frag queue timeout is set to one second in the calling script;
+        * socket timeout should be just a bit longer to avoid tests interfering
+        * with each other.
+        */
+       struct timeval tv = { .tv_sec = 1, .tv_usec = 10 };
        int idx;
        int min_frag_len = ipv6 ? 1280 : 8;
 
@@ -308,12 +366,32 @@ static void run_test(struct sockaddr *addr, socklen_t alen, bool ipv6)
                        payload_len += (rand() % 4096)) {
                if (cfg_verbose)
                        printf("payload_len: %d\n", payload_len);
-               max_frag_len = min_frag_len;
-               do {
+
+               if (cfg_overlap) {
+                       /* With overlaps, one send/receive pair below takes
+                        * at least one second (== timeout) to run, so there
+                        * is not enough test time to run a nested loop:
+                        * the full overlap test takes 20-30 seconds.
+                        */
+                       max_frag_len = min_frag_len +
+                               rand() % (1500 - FRAG_HLEN - min_frag_len);
                        send_udp_frags(fd_tx_raw, addr, alen, ipv6);
                        recv_validate_udp(fd_rx_udp);
-                       max_frag_len += 8 * (rand() % 8);
-               } while (max_frag_len < (1500 - FRAG_HLEN) && max_frag_len <= payload_len);
+               } else {
+                       /* Without overlaps, each packet reassembly (== one
+                        * send/receive pair below) takes very little time to
+                        * run, so we can easily afford more thourough testing
+                        * with a nested loop: the full non-overlap test takes
+                        * less than one second).
+                        */
+                       max_frag_len = min_frag_len;
+                       do {
+                               send_udp_frags(fd_tx_raw, addr, alen, ipv6);
+                               recv_validate_udp(fd_rx_udp);
+                               max_frag_len += 8 * (rand() % 8);
+                       } while (max_frag_len < (1500 - FRAG_HLEN) &&
+                                max_frag_len <= payload_len);
+               }
        }
 
        /* Cleanup. */
index f346727..7dd79a9 100755 (executable)
@@ -11,10 +11,17 @@ readonly NETNS="ns-$(mktemp -u XXXXXX)"
 setup() {
        ip netns add "${NETNS}"
        ip -netns "${NETNS}" link set lo up
+
        ip netns exec "${NETNS}" sysctl -w net.ipv4.ipfrag_high_thresh=9000000 >/dev/null 2>&1
        ip netns exec "${NETNS}" sysctl -w net.ipv4.ipfrag_low_thresh=7000000 >/dev/null 2>&1
+       ip netns exec "${NETNS}" sysctl -w net.ipv4.ipfrag_time=1 >/dev/null 2>&1
+
        ip netns exec "${NETNS}" sysctl -w net.ipv6.ip6frag_high_thresh=9000000 >/dev/null 2>&1
        ip netns exec "${NETNS}" sysctl -w net.ipv6.ip6frag_low_thresh=7000000 >/dev/null 2>&1
+       ip netns exec "${NETNS}" sysctl -w net.ipv6.ip6frag_time=1 >/dev/null 2>&1
+
+       # DST cache can get full with a lot of frags, with GC not keeping up with the test.
+       ip netns exec "${NETNS}" sysctl -w net.ipv6.route.max_size=65536 >/dev/null 2>&1
 }
 
 cleanup() {
@@ -27,7 +34,6 @@ setup
 echo "ipv4 defrag"
 ip netns exec "${NETNS}" ./ip_defrag -4
 
-
 echo "ipv4 defrag with overlaps"
 ip netns exec "${NETNS}" ./ip_defrag -4o
 
@@ -37,3 +43,4 @@ ip netns exec "${NETNS}" ./ip_defrag -6
 echo "ipv6 defrag with overlaps"
 ip netns exec "${NETNS}" ./ip_defrag -6o
 
+echo "all tests done"
index 8db35b9..71d7fdc 100755 (executable)
@@ -28,6 +28,19 @@ KEY_AES=0x0123456789abcdef0123456789012345
 SPI1=0x1
 SPI2=0x2
 
+do_esp_policy() {
+    local ns=$1
+    local me=$2
+    local remote=$3
+    local lnet=$4
+    local rnet=$5
+
+    # to encrypt packets as they go out (includes forwarded packets that need encapsulation)
+    ip -net $ns xfrm policy add src $lnet dst $rnet dir out tmpl src $me dst $remote proto esp mode tunnel priority 100 action allow
+    # to fwd decrypted packets after esp processing:
+    ip -net $ns xfrm policy add src $rnet dst $lnet dir fwd tmpl src $remote dst $me proto esp mode tunnel priority 100 action allow
+}
+
 do_esp() {
     local ns=$1
     local me=$2
@@ -40,10 +53,59 @@ do_esp() {
     ip -net $ns xfrm state add src $remote dst $me proto esp spi $spi_in  enc aes $KEY_AES  auth sha1 $KEY_SHA  mode tunnel sel src $rnet dst $lnet
     ip -net $ns xfrm state add src $me  dst $remote proto esp spi $spi_out enc aes $KEY_AES auth sha1 $KEY_SHA mode tunnel sel src $lnet dst $rnet
 
-    # to encrypt packets as they go out (includes forwarded packets that need encapsulation)
-    ip -net $ns xfrm policy add src $lnet dst $rnet dir out tmpl src $me dst $remote proto esp mode tunnel priority 100 action allow
-    # to fwd decrypted packets after esp processing:
-    ip -net $ns xfrm policy add src $rnet dst $lnet dir fwd tmpl src $remote dst $me proto esp mode tunnel priority 100 action allow
+    do_esp_policy $ns $me $remote $lnet $rnet
+}
+
+# add policies with different netmasks, to make sure kernel carries
+# the policies contained within new netmask over when search tree is
+# re-built.
+# peer netns that are supposed to be encapsulated via esp have addresses
+# in the 10.0.1.0/24 and 10.0.2.0/24 subnets, respectively.
+#
+# Adding a policy for '10.0.1.0/23' will make it necessary to
+# alter the prefix of 10.0.1.0 subnet.
+# In case new prefix overlaps with existing node, the node and all
+# policies it carries need to be merged with the existing one(s).
+#
+# Do that here.
+do_overlap()
+{
+    local ns=$1
+
+    # adds new nodes to tree (neither network exists yet in policy database).
+    ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/24 dir fwd priority 200 action block
+
+    # adds a new node in the 10.0.0.0/24 tree (dst node exists).
+    ip -net $ns xfrm policy add src 10.2.0.0/24 dst 10.0.0.0/24 dir fwd priority 200 action block
+
+    # adds a 10.2.0.0/23 node, but for different dst.
+    ip -net $ns xfrm policy add src 10.2.0.0/23 dst 10.0.1.0/24 dir fwd priority 200 action block
+
+    # dst now overlaps with the 10.0.1.0/24 ESP policy in fwd.
+    # kernel must 'promote' existing one (10.0.0.0/24) to 10.0.0.0/23.
+    # But 10.0.0.0/23 also includes existing 10.0.1.0/24, so that node
+    # also has to be merged too, including source-sorted subtrees.
+    # old:
+    # 10.0.0.0/24 (node 1 in dst tree of the bin)
+    #    10.1.0.0/24 (node in src tree of dst node 1)
+    #    10.2.0.0/24 (node in src tree of dst node 1)
+    # 10.0.1.0/24 (node 2 in dst tree of the bin)
+    #    10.0.2.0/24 (node in src tree of dst node 2)
+    #    10.2.0.0/24 (node in src tree of dst node 2)
+    #
+    # The next 'policy add' adds dst '10.0.0.0/23', which means
+    # that dst node 1 and dst node 2 have to be merged including
+    # the sub-tree.  As no duplicates are allowed, policies in
+    # the two '10.0.2.0/24' are also merged.
+    #
+    # after the 'add', internal search tree should look like this:
+    # 10.0.0.0/23 (node in dst tree of bin)
+    #     10.0.2.0/24 (node in src tree of dst node)
+    #     10.1.0.0/24 (node in src tree of dst node)
+    #     10.2.0.0/24 (node in src tree of dst node)
+    #
+    # 10.0.0.0/24 and 10.0.1.0/24 nodes have been merged as 10.0.0.0/23.
+    ip -net $ns xfrm policy add src 10.1.0.0/24 dst 10.0.0.0/23 dir fwd priority 200 action block
 }
 
 do_esp_policy_get_check() {
@@ -160,6 +222,41 @@ check_xfrm() {
        return $lret
 }
 
+check_exceptions()
+{
+       logpostfix="$1"
+       local lret=0
+
+       # ping to .254 should be excluded from the tunnel (exception is in place).
+       check_xfrm 0 254
+       if [ $? -ne 0 ]; then
+               echo "FAIL: expected ping to .254 to fail ($logpostfix)"
+               lret=1
+       else
+               echo "PASS: ping to .254 bypassed ipsec tunnel ($logpostfix)"
+       fi
+
+       # ping to .253 should use use ipsec due to direct policy exception.
+       check_xfrm 1 253
+       if [ $? -ne 0 ]; then
+               echo "FAIL: expected ping to .253 to use ipsec tunnel ($logpostfix)"
+               lret=1
+       else
+               echo "PASS: direct policy matches ($logpostfix)"
+       fi
+
+       # ping to .2 should use ipsec.
+       check_xfrm 1 2
+       if [ $? -ne 0 ]; then
+               echo "FAIL: expected ping to .2 to use ipsec tunnel ($logpostfix)"
+               lret=1
+       else
+               echo "PASS: policy matches ($logpostfix)"
+       fi
+
+       return $lret
+}
+
 #check for needed privileges
 if [ "$(id -u)" -ne 0 ];then
        echo "SKIP: Need root privileges"
@@ -270,33 +367,45 @@ do_exception ns4 10.0.3.10 10.0.3.1 10.0.1.253 10.0.1.240/28
 do_exception ns3 dead:3::1 dead:3::10 dead:2::fd  dead:2:f0::/96
 do_exception ns4 dead:3::10 dead:3::1 dead:1::fd  dead:1:f0::/96
 
-# ping to .254 should now be excluded from the tunnel
-check_xfrm 0 254
+check_exceptions "exceptions"
 if [ $? -ne 0 ]; then
-       echo "FAIL: expected ping to .254 to fail"
        ret=1
-else
-       echo "PASS: ping to .254 bypassed ipsec tunnel"
 fi
 
-# ping to .253 should use use ipsec due to direct policy exception.
-check_xfrm 1 253
-if [ $? -ne 0 ]; then
-       echo "FAIL: expected ping to .253 to use ipsec tunnel"
-       ret=1
-else
-       echo "PASS: direct policy matches"
-fi
+# insert block policies with adjacent/overlapping netmasks
+do_overlap ns3
 
-# ping to .2 should use ipsec.
-check_xfrm 1 2
+check_exceptions "exceptions and block policies"
 if [ $? -ne 0 ]; then
-       echo "FAIL: expected ping to .2 to use ipsec tunnel"
        ret=1
-else
-       echo "PASS: policy matches"
 fi
 
+for n in ns3 ns4;do
+       ip -net $n xfrm policy set hthresh4 28 24 hthresh6 126 125
+       sleep $((RANDOM%5))
+done
+
+check_exceptions "exceptions and block policies after hresh changes"
+
+# full flush of policy db, check everything gets freed incl. internal meta data
+ip -net ns3 xfrm policy flush
+
+do_esp_policy ns3 10.0.3.1 10.0.3.10 10.0.1.0/24 10.0.2.0/24
+do_exception ns3 10.0.3.1 10.0.3.10 10.0.2.253 10.0.2.240/28
+
+# move inexact policies to hash table
+ip -net ns3 xfrm policy set hthresh4 16 16
+
+sleep $((RANDOM%5))
+check_exceptions "exceptions and block policies after hthresh change in ns3"
+
+# restore original hthresh settings -- move policies back to tables
+for n in ns3 ns4;do
+       ip -net $n xfrm policy set hthresh4 32 32 hthresh6 128 128
+       sleep $((RANDOM%5))
+done
+check_exceptions "exceptions and block policies after hresh change to normal"
+
 for i in 1 2 3 4;do ip netns del ns$i;done
 
 exit $ret
index 47ed6ce..c9ff2b4 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 # Makefile for netfilter selftests
 
-TEST_PROGS := nft_trans_stress.sh
+TEST_PROGS := nft_trans_stress.sh nft_nat.sh
 
 include ../lib.mk
diff --git a/tools/testing/selftests/netfilter/nft_nat.sh b/tools/testing/selftests/netfilter/nft_nat.sh
new file mode 100755 (executable)
index 0000000..8ec7668
--- /dev/null
@@ -0,0 +1,762 @@
+#!/bin/bash
+#
+# This test is for basic NAT functionality: snat, dnat, redirect, masquerade.
+#
+
+# Kselftest framework requirement - SKIP code is 4.
+ksft_skip=4
+ret=0
+
+nft --version > /dev/null 2>&1
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not run test without nft tool"
+       exit $ksft_skip
+fi
+
+ip -Version > /dev/null 2>&1
+if [ $? -ne 0 ];then
+       echo "SKIP: Could not run test without ip tool"
+       exit $ksft_skip
+fi
+
+ip netns add ns0
+ip netns add ns1
+ip netns add ns2
+
+ip link add veth0 netns ns0 type veth peer name eth0 netns ns1
+ip link add veth1 netns ns0 type veth peer name eth0 netns ns2
+
+ip -net ns0 link set lo up
+ip -net ns0 link set veth0 up
+ip -net ns0 addr add 10.0.1.1/24 dev veth0
+ip -net ns0 addr add dead:1::1/64 dev veth0
+
+ip -net ns0 link set veth1 up
+ip -net ns0 addr add 10.0.2.1/24 dev veth1
+ip -net ns0 addr add dead:2::1/64 dev veth1
+
+for i in 1 2; do
+  ip -net ns$i link set lo up
+  ip -net ns$i link set eth0 up
+  ip -net ns$i addr add 10.0.$i.99/24 dev eth0
+  ip -net ns$i route add default via 10.0.$i.1
+  ip -net ns$i addr add dead:$i::99/64 dev eth0
+  ip -net ns$i route add default via dead:$i::1
+done
+
+bad_counter()
+{
+       local ns=$1
+       local counter=$2
+       local expect=$3
+
+       echo "ERROR: $counter counter in $ns has unexpected value (expected $expect)" 1>&2
+       ip netns exec $ns nft list counter inet filter $counter 1>&2
+}
+
+check_counters()
+{
+       ns=$1
+       local lret=0
+
+       cnt=$(ip netns exec $ns nft list counter inet filter ns0in | grep -q "packets 1 bytes 84")
+       if [ $? -ne 0 ]; then
+               bad_counter $ns ns0in "packets 1 bytes 84"
+               lret=1
+       fi
+       cnt=$(ip netns exec $ns nft list counter inet filter ns0out | grep -q "packets 1 bytes 84")
+       if [ $? -ne 0 ]; then
+               bad_counter $ns ns0out "packets 1 bytes 84"
+               lret=1
+       fi
+
+       expect="packets 1 bytes 104"
+       cnt=$(ip netns exec $ns nft list counter inet filter ns0in6 | grep -q "$expect")
+       if [ $? -ne 0 ]; then
+               bad_counter $ns ns0in6 "$expect"
+               lret=1
+       fi
+       cnt=$(ip netns exec $ns nft list counter inet filter ns0out6 | grep -q "$expect")
+       if [ $? -ne 0 ]; then
+               bad_counter $ns ns0out6 "$expect"
+               lret=1
+       fi
+
+       return $lret
+}
+
+check_ns0_counters()
+{
+       local ns=$1
+       local lret=0
+
+       cnt=$(ip netns exec ns0 nft list counter inet filter ns0in | grep -q "packets 0 bytes 0")
+       if [ $? -ne 0 ]; then
+               bad_counter ns0 ns0in "packets 0 bytes 0"
+               lret=1
+       fi
+
+       cnt=$(ip netns exec ns0 nft list counter inet filter ns0in6 | grep -q "packets 0 bytes 0")
+       if [ $? -ne 0 ]; then
+               bad_counter ns0 ns0in6 "packets 0 bytes 0"
+               lret=1
+       fi
+
+       cnt=$(ip netns exec ns0 nft list counter inet filter ns0out | grep -q "packets 0 bytes 0")
+       if [ $? -ne 0 ]; then
+               bad_counter ns0 ns0out "packets 0 bytes 0"
+               lret=1
+       fi
+       cnt=$(ip netns exec ns0 nft list counter inet filter ns0out6 | grep -q "packets 0 bytes 0")
+       if [ $? -ne 0 ]; then
+               bad_counter ns0 ns0out6 "packets 0 bytes 0"
+               lret=1
+       fi
+
+       for dir in "in" "out" ; do
+               expect="packets 1 bytes 84"
+               cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 $ns$dir "$expect"
+                       lret=1
+               fi
+
+               expect="packets 1 bytes 104"
+               cnt=$(ip netns exec ns0 nft list counter inet filter ${ns}${dir}6 | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 $ns$dir6 "$expect"
+                       lret=1
+               fi
+       done
+
+       return $lret
+}
+
+reset_counters()
+{
+       for i in 0 1 2;do
+               ip netns exec ns$i nft reset counters inet > /dev/null
+       done
+}
+
+test_local_dnat6()
+{
+       local lret=0
+ip netns exec ns0 nft -f - <<EOF
+table ip6 nat {
+       chain output {
+               type nat hook output priority 0; policy accept;
+               ip6 daddr dead:1::99 dnat to dead:2::99
+       }
+}
+EOF
+       if [ $? -ne 0 ]; then
+               echo "SKIP: Could not add add ip6 dnat hook"
+               return $ksft_skip
+       fi
+
+       # ping netns1, expect rewrite to netns2
+       ip netns exec ns0 ping -q -c 1 dead:1::99 > /dev/null
+       if [ $? -ne 0 ]; then
+               lret=1
+               echo "ERROR: ping6 failed"
+               return $lret
+       fi
+
+       expect="packets 0 bytes 0"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns2$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 0 count in ns1
+       expect="packets 0 bytes 0"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 1 packet in ns2
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       test $lret -eq 0 && echo "PASS: ipv6 ping to ns1 was NATted to ns2"
+       ip netns exec ns0 nft flush chain ip6 nat output
+
+       return $lret
+}
+
+test_local_dnat()
+{
+       local lret=0
+ip netns exec ns0 nft -f - <<EOF
+table ip nat {
+       chain output {
+               type nat hook output priority 0; policy accept;
+               ip daddr 10.0.1.99 dnat to 10.0.2.99
+       }
+}
+EOF
+       # ping netns1, expect rewrite to netns2
+       ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
+       if [ $? -ne 0 ]; then
+               lret=1
+               echo "ERROR: ping failed"
+               return $lret
+       fi
+
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns2$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 0 count in ns1
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 1 packet in ns2
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       test $lret -eq 0 && echo "PASS: ping to ns1 was NATted to ns2"
+
+       ip netns exec ns0 nft flush chain ip nat output
+
+       reset_counters
+       ip netns exec ns0 ping -q -c 1 10.0.1.99 > /dev/null
+       if [ $? -ne 0 ]; then
+               lret=1
+               echo "ERROR: ping failed"
+               return $lret
+       fi
+
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns2$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 1 count in ns1
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns0 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # expect 0 packet in ns2
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns2$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       test $lret -eq 0 && echo "PASS: ping to ns1 OK after nat output chain flush"
+
+       return $lret
+}
+
+
+test_masquerade6()
+{
+       local lret=0
+
+       ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
+
+       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2 via ipv6"
+               return 1
+               lret=1
+       fi
+
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns2$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       reset_counters
+
+# add masquerading rule
+ip netns exec ns0 nft -f - <<EOF
+table ip6 nat {
+       chain postrouting {
+               type nat hook postrouting priority 0; policy accept;
+               meta oif veth0 masquerade
+       }
+}
+EOF
+       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2 with active ipv6 masquerading"
+               lret=1
+       fi
+
+       # ns1 should have seen packets from ns0, due to masquerade
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # ns1 should not have seen packets from ns2, due to masquerade
+       expect="packets 0 bytes 0"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       ip netns exec ns0 nft flush chain ip6 nat postrouting
+       if [ $? -ne 0 ]; then
+               echo "ERROR: Could not flush ip6 nat postrouting" 1>&2
+               lret=1
+       fi
+
+       test $lret -eq 0 && echo "PASS: IPv6 masquerade for ns2"
+
+       return $lret
+}
+
+test_masquerade()
+{
+       local lret=0
+
+       ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
+       ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
+
+       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: canot ping ns1 from ns2"
+               lret=1
+       fi
+
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns2$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       reset_counters
+
+# add masquerading rule
+ip netns exec ns0 nft -f - <<EOF
+table ip nat {
+       chain postrouting {
+               type nat hook postrouting priority 0; policy accept;
+               meta oif veth0 masquerade
+       }
+}
+EOF
+       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2 with active ip masquerading"
+               lret=1
+       fi
+
+       # ns1 should have seen packets from ns0, due to masquerade
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns0${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # ns1 should not have seen packets from ns2, due to masquerade
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       ip netns exec ns0 nft flush chain ip nat postrouting
+       if [ $? -ne 0 ]; then
+               echo "ERROR: Could not flush nat postrouting" 1>&2
+               lret=1
+       fi
+
+       test $lret -eq 0 && echo "PASS: IP masquerade for ns2"
+
+       return $lret
+}
+
+test_redirect6()
+{
+       local lret=0
+
+       ip netns exec ns0 sysctl net.ipv6.conf.all.forwarding=1 > /dev/null
+
+       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannnot ping ns1 from ns2 via ipv6"
+               lret=1
+       fi
+
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns2$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       reset_counters
+
+# add redirect rule
+ip netns exec ns0 nft -f - <<EOF
+table ip6 nat {
+       chain prerouting {
+               type nat hook prerouting priority 0; policy accept;
+               meta iif veth1 meta l4proto icmpv6 ip6 saddr dead:2::99 ip6 daddr dead:1::99 redirect
+       }
+}
+EOF
+       ip netns exec ns2 ping -q -c 1 dead:1::99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2 with active ip6 redirect"
+               lret=1
+       fi
+
+       # ns1 should have seen no packets from ns2, due to redirection
+       expect="packets 0 bytes 0"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # ns0 should have seen packets from ns2, due to masquerade
+       expect="packets 1 bytes 104"
+       for dir in "in6" "out6" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       ip netns exec ns0 nft delete table ip6 nat
+       if [ $? -ne 0 ]; then
+               echo "ERROR: Could not delete ip6 nat table" 1>&2
+               lret=1
+       fi
+
+       test $lret -eq 0 && echo "PASS: IPv6 redirection for ns2"
+
+       return $lret
+}
+
+test_redirect()
+{
+       local lret=0
+
+       ip netns exec ns0 sysctl net.ipv4.conf.veth0.forwarding=1 > /dev/null
+       ip netns exec ns0 sysctl net.ipv4.conf.veth1.forwarding=1 > /dev/null
+
+       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2"
+               lret=1
+       fi
+
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns2$dir "$expect"
+                       lret=1
+               fi
+
+               cnt=$(ip netns exec ns2 nft list counter inet filter ns1${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns2 ns1$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       reset_counters
+
+# add redirect rule
+ip netns exec ns0 nft -f - <<EOF
+table ip nat {
+       chain prerouting {
+               type nat hook prerouting priority 0; policy accept;
+               meta iif veth1 ip protocol icmp ip saddr 10.0.2.99 ip daddr 10.0.1.99 redirect
+       }
+}
+EOF
+       ip netns exec ns2 ping -q -c 1 10.0.1.99 > /dev/null # ping ns2->ns1
+       if [ $? -ne 0 ] ; then
+               echo "ERROR: cannot ping ns1 from ns2 with active ip redirect"
+               lret=1
+       fi
+
+       # ns1 should have seen no packets from ns2, due to redirection
+       expect="packets 0 bytes 0"
+       for dir in "in" "out" ; do
+
+               cnt=$(ip netns exec ns1 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       # ns0 should have seen packets from ns2, due to masquerade
+       expect="packets 1 bytes 84"
+       for dir in "in" "out" ; do
+               cnt=$(ip netns exec ns0 nft list counter inet filter ns2${dir} | grep -q "$expect")
+               if [ $? -ne 0 ]; then
+                       bad_counter ns1 ns0$dir "$expect"
+                       lret=1
+               fi
+       done
+
+       ip netns exec ns0 nft delete table ip nat
+       if [ $? -ne 0 ]; then
+               echo "ERROR: Could not delete nat table" 1>&2
+               lret=1
+       fi
+
+       test $lret -eq 0 && echo "PASS: IP redirection for ns2"
+
+       return $lret
+}
+
+
+# ip netns exec ns0 ping -c 1 -q 10.0.$i.99
+for i in 0 1 2; do
+ip netns exec ns$i nft -f - <<EOF
+table inet filter {
+       counter ns0in {}
+       counter ns1in {}
+       counter ns2in {}
+
+       counter ns0out {}
+       counter ns1out {}
+       counter ns2out {}
+
+       counter ns0in6 {}
+       counter ns1in6 {}
+       counter ns2in6 {}
+
+       counter ns0out6 {}
+       counter ns1out6 {}
+       counter ns2out6 {}
+
+       map nsincounter {
+               type ipv4_addr : counter
+               elements = { 10.0.1.1 : "ns0in",
+                            10.0.2.1 : "ns0in",
+                            10.0.1.99 : "ns1in",
+                            10.0.2.99 : "ns2in" }
+       }
+
+       map nsincounter6 {
+               type ipv6_addr : counter
+               elements = { dead:1::1 : "ns0in6",
+                            dead:2::1 : "ns0in6",
+                            dead:1::99 : "ns1in6",
+                            dead:2::99 : "ns2in6" }
+       }
+
+       map nsoutcounter {
+               type ipv4_addr : counter
+               elements = { 10.0.1.1 : "ns0out",
+                            10.0.2.1 : "ns0out",
+                            10.0.1.99: "ns1out",
+                            10.0.2.99: "ns2out" }
+       }
+
+       map nsoutcounter6 {
+               type ipv6_addr : counter
+               elements = { dead:1::1 : "ns0out6",
+                            dead:2::1 : "ns0out6",
+                            dead:1::99 : "ns1out6",
+                            dead:2::99 : "ns2out6" }
+       }
+
+       chain input {
+               type filter hook input priority 0; policy accept;
+               counter name ip saddr map @nsincounter
+               icmpv6 type { "echo-request", "echo-reply" } counter name ip6 saddr map @nsincounter6
+       }
+       chain output {
+               type filter hook output priority 0; policy accept;
+               counter name ip daddr map @nsoutcounter
+               icmpv6 type { "echo-request", "echo-reply" } counter name ip6 daddr map @nsoutcounter6
+       }
+}
+EOF
+done
+
+sleep 3
+# test basic connectivity
+for i in 1 2; do
+  ip netns exec ns0 ping -c 1 -q 10.0.$i.99 > /dev/null
+  if [ $? -ne 0 ];then
+       echo "ERROR: Could not reach other namespace(s)" 1>&2
+       ret=1
+  fi
+
+  ip netns exec ns0 ping -c 1 -q dead:$i::99 > /dev/null
+  if [ $? -ne 0 ];then
+       echo "ERROR: Could not reach other namespace(s) via ipv6" 1>&2
+       ret=1
+  fi
+  check_counters ns$i
+  if [ $? -ne 0 ]; then
+       ret=1
+  fi
+
+  check_ns0_counters ns$i
+  if [ $? -ne 0 ]; then
+       ret=1
+  fi
+  reset_counters
+done
+
+if [ $ret -eq 0 ];then
+       echo "PASS: netns routing/connectivity: ns0 can reach ns1 and ns2"
+fi
+
+reset_counters
+test_local_dnat
+test_local_dnat6
+
+reset_counters
+test_masquerade
+test_masquerade6
+
+reset_counters
+test_redirect
+test_redirect6
+
+for i in 0 1 2; do ip netns del ns$i;done
+
+exit $ret
index 9050eee..1de8bd8 100644 (file)
@@ -9,6 +9,3 @@ all: $(TEST_PROGS)
 top_srcdir = ../../../../..
 KSFT_KHDR_INSTALL := 1
 include ../../lib.mk
-
-clean:
-       rm -fr $(TEST_GEN_FILES)
index 2e563d1..d1bbafb 100644 (file)
@@ -240,7 +240,7 @@ static void __recv_errmsg_cmsg(struct msghdr *msg, int payload_len)
                            cm->cmsg_type == IP_RECVERR) ||
                           (cm->cmsg_level == SOL_IPV6 &&
                            cm->cmsg_type == IPV6_RECVERR) ||
-                          (cm->cmsg_level = SOL_PACKET &&
+                          (cm->cmsg_level == SOL_PACKET &&
                            cm->cmsg_type == PACKET_TX_TIMESTAMP)) {
                        serr = (void *) CMSG_DATA(cm);
                        if (serr->ee_errno != ENOMSG ||
index 82121a8..29bac5e 100644 (file)
@@ -10,4 +10,5 @@
 /proc-uptime-002
 /read
 /self
+/setns-dcache
 /thread-self
index 1c12c34..434d033 100644 (file)
@@ -14,6 +14,7 @@ TEST_GEN_PROGS += proc-uptime-001
 TEST_GEN_PROGS += proc-uptime-002
 TEST_GEN_PROGS += read
 TEST_GEN_PROGS += self
+TEST_GEN_PROGS += setns-dcache
 TEST_GEN_PROGS += thread-self
 
 include ../lib.mk
diff --git a/tools/testing/selftests/proc/setns-dcache.c b/tools/testing/selftests/proc/setns-dcache.c
new file mode 100644 (file)
index 0000000..60ab197
--- /dev/null
@@ -0,0 +1,129 @@
+/*
+ * Copyright Â© 2019 Alexey Dobriyan <adobriyan@gmail.com>
+ *
+ * Permission to use, copy, modify, and distribute this software for any
+ * purpose with or without fee is hereby granted, provided that the above
+ * copyright notice and this permission notice appear in all copies.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
+ * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
+ * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
+ * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
+ * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
+ * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
+ * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
+ */
+/*
+ * Test that setns(CLONE_NEWNET) points to new /proc/net content even
+ * if old one is in dcache.
+ *
+ * FIXME /proc/net/unix is under CONFIG_UNIX which can be disabled.
+ */
+#undef NDEBUG
+#include <assert.h>
+#include <errno.h>
+#include <sched.h>
+#include <signal.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/types.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sys/socket.h>
+
+static pid_t pid = -1;
+
+static void f(void)
+{
+       if (pid > 0) {
+               kill(pid, SIGTERM);
+       }
+}
+
+int main(void)
+{
+       int fd[2];
+       char _ = 0;
+       int nsfd;
+
+       atexit(f);
+
+       /* Check for priviledges and syscall availability straight away. */
+       if (unshare(CLONE_NEWNET) == -1) {
+               if (errno == ENOSYS || errno == EPERM) {
+                       return 4;
+               }
+               return 1;
+       }
+       /* Distinguisher between two otherwise empty net namespaces. */
+       if (socket(AF_UNIX, SOCK_STREAM, 0) == -1) {
+               return 1;
+       }
+
+       if (pipe(fd) == -1) {
+               return 1;
+       }
+
+       pid = fork();
+       if (pid == -1) {
+               return 1;
+       }
+
+       if (pid == 0) {
+               if (unshare(CLONE_NEWNET) == -1) {
+                       return 1;
+               }
+
+               if (write(fd[1], &_, 1) != 1) {
+                       return 1;
+               }
+
+               pause();
+
+               return 0;
+       }
+
+       if (read(fd[0], &_, 1) != 1) {
+               return 1;
+       }
+
+       {
+               char buf[64];
+               snprintf(buf, sizeof(buf), "/proc/%u/ns/net", pid);
+               nsfd = open(buf, O_RDONLY);
+               if (nsfd == -1) {
+                       return 1;
+               }
+       }
+
+       /* Reliably pin dentry into dcache. */
+       (void)open("/proc/net/unix", O_RDONLY);
+
+       if (setns(nsfd, CLONE_NEWNET) == -1) {
+               return 1;
+       }
+
+       kill(pid, SIGTERM);
+       pid = 0;
+
+       {
+               char buf[4096];
+               ssize_t rv;
+               int fd;
+
+               fd = open("/proc/net/unix", O_RDONLY);
+               if (fd == -1) {
+                       return 1;
+               }
+
+#define S "Num       RefCount Protocol Flags    Type St Inode Path\n"
+               rv = read(fd, buf, sizeof(buf));
+
+               assert(rv == strlen(S));
+               assert(memcmp(buf, S, strlen(S)) == 0);
+       }
+
+       return 0;
+}
index e20b017..b206553 100644 (file)
@@ -145,15 +145,12 @@ TEST_F(rtc, alarm_alm_set) {
 
        rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
        ASSERT_NE(-1, rc);
-       EXPECT_NE(0, rc);
+       ASSERT_NE(0, rc);
 
        /* Disable alarm interrupts */
        rc = ioctl(self->fd, RTC_AIE_OFF, 0);
        ASSERT_NE(-1, rc);
 
-       if (rc == 0)
-               return;
-
        rc = read(self->fd, &data, sizeof(unsigned long));
        ASSERT_NE(-1, rc);
        TH_LOG("data: %lx", data);
@@ -202,7 +199,109 @@ TEST_F(rtc, alarm_wkalm_set) {
 
        rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
        ASSERT_NE(-1, rc);
-       EXPECT_NE(0, rc);
+       ASSERT_NE(0, rc);
+
+       rc = read(self->fd, &data, sizeof(unsigned long));
+       ASSERT_NE(-1, rc);
+
+       rc = ioctl(self->fd, RTC_RD_TIME, &tm);
+       ASSERT_NE(-1, rc);
+
+       new = timegm((struct tm *)&tm);
+       ASSERT_EQ(new, secs);
+}
+
+TEST_F(rtc, alarm_alm_set_minute) {
+       struct timeval tv = { .tv_sec = 62 };
+       unsigned long data;
+       struct rtc_time tm;
+       fd_set readfds;
+       time_t secs, new;
+       int rc;
+
+       rc = ioctl(self->fd, RTC_RD_TIME, &tm);
+       ASSERT_NE(-1, rc);
+
+       secs = timegm((struct tm *)&tm) + 60 - tm.tm_sec;
+       gmtime_r(&secs, (struct tm *)&tm);
+
+       rc = ioctl(self->fd, RTC_ALM_SET, &tm);
+       if (rc == -1) {
+               ASSERT_EQ(EINVAL, errno);
+               TH_LOG("skip alarms are not supported.");
+               return;
+       }
+
+       rc = ioctl(self->fd, RTC_ALM_READ, &tm);
+       ASSERT_NE(-1, rc);
+
+       TH_LOG("Alarm time now set to %02d:%02d:%02d.",
+              tm.tm_hour, tm.tm_min, tm.tm_sec);
+
+       /* Enable alarm interrupts */
+       rc = ioctl(self->fd, RTC_AIE_ON, 0);
+       ASSERT_NE(-1, rc);
+
+       FD_ZERO(&readfds);
+       FD_SET(self->fd, &readfds);
+
+       rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
+       ASSERT_NE(-1, rc);
+       ASSERT_NE(0, rc);
+
+       /* Disable alarm interrupts */
+       rc = ioctl(self->fd, RTC_AIE_OFF, 0);
+       ASSERT_NE(-1, rc);
+
+       rc = read(self->fd, &data, sizeof(unsigned long));
+       ASSERT_NE(-1, rc);
+       TH_LOG("data: %lx", data);
+
+       rc = ioctl(self->fd, RTC_RD_TIME, &tm);
+       ASSERT_NE(-1, rc);
+
+       new = timegm((struct tm *)&tm);
+       ASSERT_EQ(new, secs);
+}
+
+TEST_F(rtc, alarm_wkalm_set_minute) {
+       struct timeval tv = { .tv_sec = 62 };
+       struct rtc_wkalrm alarm = { 0 };
+       struct rtc_time tm;
+       unsigned long data;
+       fd_set readfds;
+       time_t secs, new;
+       int rc;
+
+       rc = ioctl(self->fd, RTC_RD_TIME, &alarm.time);
+       ASSERT_NE(-1, rc);
+
+       secs = timegm((struct tm *)&alarm.time) + 60 - alarm.time.tm_sec;
+       gmtime_r(&secs, (struct tm *)&alarm.time);
+
+       alarm.enabled = 1;
+
+       rc = ioctl(self->fd, RTC_WKALM_SET, &alarm);
+       if (rc == -1) {
+               ASSERT_EQ(EINVAL, errno);
+               TH_LOG("skip alarms are not supported.");
+               return;
+       }
+
+       rc = ioctl(self->fd, RTC_WKALM_RD, &alarm);
+       ASSERT_NE(-1, rc);
+
+       TH_LOG("Alarm time now set to %02d/%02d/%02d %02d:%02d:%02d.",
+              alarm.time.tm_mday, alarm.time.tm_mon + 1,
+              alarm.time.tm_year + 1900, alarm.time.tm_hour,
+              alarm.time.tm_min, alarm.time.tm_sec);
+
+       FD_ZERO(&readfds);
+       FD_SET(self->fd, &readfds);
+
+       rc = select(self->fd + 1, &readfds, NULL, NULL, &tv);
+       ASSERT_NE(-1, rc);
+       ASSERT_NE(0, rc);
 
        rc = read(self->fd, &data, sizeof(unsigned long));
        ASSERT_NE(-1, rc);
index fce7f4c..1760b3e 100644 (file)
@@ -9,7 +9,7 @@ BINARIES := seccomp_bpf seccomp_benchmark
 CFLAGS += -Wl,-no-as-needed -Wall
 
 seccomp_bpf: seccomp_bpf.c ../kselftest_harness.h
-       $(CC) $(CFLAGS) $(LDFLAGS) -lpthread $< -o $@
+       $(CC) $(CFLAGS) $(LDFLAGS) $< -lpthread -o $@
 
 TEST_PROGS += $(BINARIES)
 EXTRA_CLEAN := $(BINARIES)
index 067cb46..7e632b4 100644 (file)
@@ -1608,7 +1608,16 @@ TEST_F(TRACE_poke, getpid_runs_normally)
 #ifdef SYSCALL_NUM_RET_SHARE_REG
 # define EXPECT_SYSCALL_RETURN(val, action)    EXPECT_EQ(-1, action)
 #else
-# define EXPECT_SYSCALL_RETURN(val, action)    EXPECT_EQ(val, action)
+# define EXPECT_SYSCALL_RETURN(val, action)            \
+       do {                                            \
+               errno = 0;                              \
+               if (val < 0) {                          \
+                       EXPECT_EQ(-1, action);          \
+                       EXPECT_EQ(-(val), errno);       \
+               } else {                                \
+                       EXPECT_EQ(val, action);         \
+               }                                       \
+       } while (0)
 #endif
 
 /* Use PTRACE_GETREGS and PTRACE_SETREGS when available. This is useful for
@@ -1647,7 +1656,7 @@ int get_syscall(struct __test_metadata *_metadata, pid_t tracee)
 
 /* Architecture-specific syscall changing routine. */
 void change_syscall(struct __test_metadata *_metadata,
-                   pid_t tracee, int syscall)
+                   pid_t tracee, int syscall, int result)
 {
        int ret;
        ARCH_REGS regs;
@@ -1706,7 +1715,7 @@ void change_syscall(struct __test_metadata *_metadata,
 #ifdef SYSCALL_NUM_RET_SHARE_REG
                TH_LOG("Can't modify syscall return on this architecture");
 #else
-               regs.SYSCALL_RET = EPERM;
+               regs.SYSCALL_RET = result;
 #endif
 
 #ifdef HAVE_GETREGS
@@ -1734,14 +1743,19 @@ void tracer_syscall(struct __test_metadata *_metadata, pid_t tracee,
        case 0x1002:
                /* change getpid to getppid. */
                EXPECT_EQ(__NR_getpid, get_syscall(_metadata, tracee));
-               change_syscall(_metadata, tracee, __NR_getppid);
+               change_syscall(_metadata, tracee, __NR_getppid, 0);
                break;
        case 0x1003:
-               /* skip gettid. */
+               /* skip gettid with valid return code. */
                EXPECT_EQ(__NR_gettid, get_syscall(_metadata, tracee));
-               change_syscall(_metadata, tracee, -1);
+               change_syscall(_metadata, tracee, -1, 45000);
                break;
        case 0x1004:
+               /* skip openat with error. */
+               EXPECT_EQ(__NR_openat, get_syscall(_metadata, tracee));
+               change_syscall(_metadata, tracee, -1, -ESRCH);
+               break;
+       case 0x1005:
                /* do nothing (allow getppid) */
                EXPECT_EQ(__NR_getppid, get_syscall(_metadata, tracee));
                break;
@@ -1774,9 +1788,11 @@ void tracer_ptrace(struct __test_metadata *_metadata, pid_t tracee,
        nr = get_syscall(_metadata, tracee);
 
        if (nr == __NR_getpid)
-               change_syscall(_metadata, tracee, __NR_getppid);
+               change_syscall(_metadata, tracee, __NR_getppid, 0);
+       if (nr == __NR_gettid)
+               change_syscall(_metadata, tracee, -1, 45000);
        if (nr == __NR_openat)
-               change_syscall(_metadata, tracee, -1);
+               change_syscall(_metadata, tracee, -1, -ESRCH);
 }
 
 FIXTURE_DATA(TRACE_syscall) {
@@ -1793,8 +1809,10 @@ FIXTURE_SETUP(TRACE_syscall)
                BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1002),
                BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_gettid, 0, 1),
                BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1003),
-               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_openat, 0, 1),
                BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1004),
+               BPF_JUMP(BPF_JMP|BPF_JEQ|BPF_K, __NR_getppid, 0, 1),
+               BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_TRACE | 0x1005),
                BPF_STMT(BPF_RET|BPF_K, SECCOMP_RET_ALLOW),
        };
 
@@ -1842,15 +1860,26 @@ TEST_F(TRACE_syscall, ptrace_syscall_redirected)
        EXPECT_NE(self->mypid, syscall(__NR_getpid));
 }
 
-TEST_F(TRACE_syscall, ptrace_syscall_dropped)
+TEST_F(TRACE_syscall, ptrace_syscall_errno)
+{
+       /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
+       teardown_trace_fixture(_metadata, self->tracer);
+       self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
+                                          true);
+
+       /* Tracer should skip the open syscall, resulting in ESRCH. */
+       EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
+}
+
+TEST_F(TRACE_syscall, ptrace_syscall_faked)
 {
        /* Swap SECCOMP_RET_TRACE tracer for PTRACE_SYSCALL tracer. */
        teardown_trace_fixture(_metadata, self->tracer);
        self->tracer = setup_trace_fixture(_metadata, tracer_ptrace, NULL,
                                           true);
 
-       /* Tracer should skip the open syscall, resulting in EPERM. */
-       EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_openat));
+       /* Tracer should skip the gettid syscall, resulting fake pid. */
+       EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
 }
 
 TEST_F(TRACE_syscall, syscall_allowed)
@@ -1883,7 +1912,21 @@ TEST_F(TRACE_syscall, syscall_redirected)
        EXPECT_NE(self->mypid, syscall(__NR_getpid));
 }
 
-TEST_F(TRACE_syscall, syscall_dropped)
+TEST_F(TRACE_syscall, syscall_errno)
+{
+       long ret;
+
+       ret = prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0);
+       ASSERT_EQ(0, ret);
+
+       ret = prctl(PR_SET_SECCOMP, SECCOMP_MODE_FILTER, &self->prog, 0, 0);
+       ASSERT_EQ(0, ret);
+
+       /* openat has been skipped and an errno return. */
+       EXPECT_SYSCALL_RETURN(-ESRCH, syscall(__NR_openat));
+}
+
+TEST_F(TRACE_syscall, syscall_faked)
 {
        long ret;
 
@@ -1894,8 +1937,7 @@ TEST_F(TRACE_syscall, syscall_dropped)
        ASSERT_EQ(0, ret);
 
        /* gettid has been skipped and an altered return value stored. */
-       EXPECT_SYSCALL_RETURN(EPERM, syscall(__NR_gettid));
-       EXPECT_NE(self->mytid, syscall(__NR_gettid));
+       EXPECT_SYSCALL_RETURN(45000, syscall(__NR_gettid));
 }
 
 TEST_F(TRACE_syscall, skip_after_RET_TRACE)
@@ -3044,7 +3086,7 @@ TEST(user_notification_basic)
        /* Check that the basic notification machinery works */
        listener = user_trap_syscall(__NR_getpid,
                                     SECCOMP_FILTER_FLAG_NEW_LISTENER);
-       EXPECT_GE(listener, 0);
+       ASSERT_GE(listener, 0);
 
        /* Installing a second listener in the chain should EBUSY */
        EXPECT_EQ(user_trap_syscall(__NR_getpid,
@@ -3103,7 +3145,7 @@ TEST(user_notification_kill_in_middle)
 
        listener = user_trap_syscall(__NR_getpid,
                                     SECCOMP_FILTER_FLAG_NEW_LISTENER);
-       EXPECT_GE(listener, 0);
+       ASSERT_GE(listener, 0);
 
        /*
         * Check that nothing bad happens when we kill the task in the middle
@@ -3152,7 +3194,7 @@ TEST(user_notification_signal)
 
        listener = user_trap_syscall(__NR_gettid,
                                     SECCOMP_FILTER_FLAG_NEW_LISTENER);
-       EXPECT_GE(listener, 0);
+       ASSERT_GE(listener, 0);
 
        pid = fork();
        ASSERT_GE(pid, 0);
@@ -3215,7 +3257,7 @@ TEST(user_notification_closed_listener)
 
        listener = user_trap_syscall(__NR_getpid,
                                     SECCOMP_FILTER_FLAG_NEW_LISTENER);
-       EXPECT_GE(listener, 0);
+       ASSERT_GE(listener, 0);
 
        /*
         * Check that we get an ENOSYS when the listener is closed.
@@ -3376,7 +3418,7 @@ TEST(seccomp_get_notif_sizes)
 {
        struct seccomp_notif_sizes sizes;
 
-       EXPECT_EQ(seccomp(SECCOMP_GET_NOTIF_SIZES, 0, &sizes), 0);
+       ASSERT_EQ(seccomp(SECCOMP_GET_NOTIF_SIZES, 0, &sizes), 0);
        EXPECT_EQ(sizes.seccomp_notif, sizeof(struct seccomp_notif));
        EXPECT_EQ(sizes.seccomp_notif_resp, sizeof(struct seccomp_notif_resp));
 }
index 637ea02..0da3545 100644 (file)
@@ -17,7 +17,7 @@
         "cmdUnderTest": "$TC actions add action ife encode allow mark pass index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow mark.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow mark.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
@@ -41,7 +41,7 @@
         "cmdUnderTest": "$TC actions add action ife encode use mark 10 pipe index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use mark.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use mark.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
@@ -65,7 +65,7 @@
         "cmdUnderTest": "$TC actions add action ife encode allow mark continue index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0xED3E.*allow mark.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0[xX]ED3E.*allow mark.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
@@ -89,7 +89,7 @@
         "cmdUnderTest": "$TC actions add action ife encode use mark 789 drop index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0xED3E.*use mark 789.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0[xX]ED3E.*use mark 789.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use mark 656768 reclassify index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*use mark 656768.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*use mark 656768.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use mark 65 jump 1 index 2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 2",
-        "matchPattern": "action order [0-9]*: ife encode action jump 1.*type 0xED3E.*use mark 65.*index 2",
+        "matchPattern": "action order [0-9]*: ife encode action jump 1.*type 0[xX]ED3E.*use mark 65.*index 2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use mark 4294967295 reclassify index 90",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 90",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*use mark 4294967295.*index 90",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*use mark 4294967295.*index 90",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use mark 4294967295999 pipe index 90",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 90",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use mark 4294967295999.*index 90",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use mark 4294967295999.*index 90",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow prio pass index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow prio.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow prio.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 7 pipe index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use prio 7.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use prio 7.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 3 continue index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0xED3E.*use prio 3.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0[xX]ED3E.*use prio 3.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow prio drop index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0xED3E.*allow prio.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0[xX]ED3E.*allow prio.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 998877 reclassify index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*use prio 998877.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*use prio 998877.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 998877 jump 10 index 9",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 9",
-        "matchPattern": "action order [0-9]*: ife encode action jump 10.*type 0xED3E.*use prio 998877.*index 9",
+        "matchPattern": "action order [0-9]*: ife encode action jump 10.*type 0[xX]ED3E.*use prio 998877.*index 9",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 4294967295 reclassify index 99",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 99",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*use prio 4294967295.*index 99",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*use prio 4294967295.*index 99",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 4294967298 pipe index 99",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 99",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use prio 4294967298.*index 99",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use prio 4294967298.*index 99",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow tcindex pass index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow tcindex.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow tcindex.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 111 pipe index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use tcindex 111.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use tcindex 111.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 1 continue index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0xED3E.*use tcindex 1.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0[xX]ED3E.*use tcindex 1.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 1 continue index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0xED3E.*use tcindex 1.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action continue.*type 0[xX]ED3E.*use tcindex 1.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow tcindex drop index 77",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 77",
-        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0xED3E.*allow tcindex.*index 77",
+        "matchPattern": "action order [0-9]*: ife encode action drop.*type 0[xX]ED3E.*allow tcindex.*index 77",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow tcindex reclassify index 77",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 77",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*allow tcindex.*index 77",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*allow tcindex.*index 77",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow tcindex jump 999 index 77",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 77",
-        "matchPattern": "action order [0-9]*: ife encode action jump 999.*type 0xED3E.*allow tcindex.*index 77",
+        "matchPattern": "action order [0-9]*: ife encode action jump 999.*type 0[xX]ED3E.*allow tcindex.*index 77",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 65535 pass index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*use tcindex 65535.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*use tcindex 65535.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 65539 pipe index 1",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*use tcindex 65539.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*use tcindex 65539.*index 1",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow mark src 00:11:22:33:44:55 pipe index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*allow mark src 00:11:22:33:44:55.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*allow mark src 00:11:22:33:44:55.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 9876 dst 00:11:22:33:44:55 reclassify index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xED3E.*use prio 9876 dst 00:11:22:33:44:55.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ED3E.*use prio 9876 dst 00:11:22:33:44:55.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow tcindex src 00:aa:bb:cc:dd:ee dst 00:11:22:33:44:55 pass index 11",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 11",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow tcindex dst 00:11:22:33:44:55 src 00:aa:bb:cc:dd:ee .*index 11",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow tcindex dst 00:11:22:33:44:55 src 00:aa:bb:cc:dd:ee .*index 11",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use mark 7 type 0xfefe pass index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xFEFE.*use mark 7.*index 1",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]FEFE.*use mark 7.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use prio 444 type 0xabba pipe index 21",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 21",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xABBA.*use prio 444.*index 21",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ABBA.*use prio 444.*index 21",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode use tcindex 5000 type 0xabcd reclassify index 21",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 21",
-        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0xABCD.*use tcindex 5000.*index 21",
+        "matchPattern": "action order [0-9]*: ife encode action reclassify.*type 0[xX]ABCD.*use tcindex 5000.*index 21",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
     },
     {
         "id": "fac3",
-        "name": "Create valid ife encode action with index at 32-bit maximnum",
+        "name": "Create valid ife encode action with index at 32-bit maximum",
         "category": [
             "actions",
             "ife"
         "cmdUnderTest": "$TC actions add action ife encode allow mark pass index 4294967295",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 4294967295",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow mark.*index 4294967295",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow mark.*index 4294967295",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode pass index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action pass.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action pass.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode pipe index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action pipe.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action pipe.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode continue index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action continue.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action continue.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode drop index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action drop.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action drop.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode reclassify index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action reclassify.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action reclassify.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife decode jump 10 index 1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 1",
-        "matchPattern": "action order [0-9]*: ife decode action jump 10.*type 0x0.*allow mark allow tcindex allow prio.*index 1",
+        "matchPattern": "action order [0-9]*: ife decode action jump 10.*type 0(x0)?.*allow mark allow tcindex allow prio.*index 1",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow mark pass index 4294967295999",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 4294967295999",
-        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0xED3E.*allow mark.*index 4294967295999",
+        "matchPattern": "action order [0-9]*: ife encode action pass.*type 0[xX]ED3E.*allow mark.*index 4294967295999",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow mark kuka index 4",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 4",
-        "matchPattern": "action order [0-9]*: ife encode action kuka.*type 0xED3E.*allow mark.*index 4",
+        "matchPattern": "action order [0-9]*: ife encode action kuka.*type 0[xX]ED3E.*allow mark.*index 4",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow prio pipe index 4 cookie aabbccddeeff112233445566778800a1",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action ife index 4",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*allow prio.*index 4.*cookie aabbccddeeff112233445566778800a1",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*allow prio.*index 4.*cookie aabbccddeeff112233445566778800a1",
         "matchCount": "1",
         "teardown": [
            "$TC actions flush action ife"
         "cmdUnderTest": "$TC actions add action ife encode allow foo pipe index 4",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 4",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0xED3E.*allow foo.*index 4",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]ED3E.*allow foo.*index 4",
         "matchCount": "0",
         "teardown": []
     },
         "cmdUnderTest": "$TC actions add action ife encode allow prio type 70000 pipe index 4",
         "expExitCode": "255",
         "verifyCmd": "$TC actions get action ife index 4",
-        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0x11170.*allow prio.*index 4",
+        "matchPattern": "action order [0-9]*: ife encode action pipe.*type 0[xX]11170.*allow prio.*index 4",
         "matchCount": "0",
         "teardown": []
     },
index 10b2d89..e7e15a7 100644 (file)
            ]
         ]
     },
-    {
-        "id": "ba4e",
-        "name": "Add tunnel_key set action with missing mandatory id parameter",
-        "category": [
-            "actions",
-            "tunnel_key"
-        ],
-        "setup": [
-            [
-                "$TC actions flush action tunnel_key",
-                0,
-                1,
-                255
-            ]
-        ],
-        "cmdUnderTest": "$TC actions add action tunnel_key set src_ip 10.10.10.1 dst_ip 20.20.20.2",
-        "expExitCode": "255",
-        "verifyCmd": "$TC actions list action tunnel_key",
-        "matchPattern": "action order [0-9]+: tunnel_key set.*src_ip 10.10.10.1.*dst_ip 20.20.20.2",
-        "matchCount": "0",
-        "teardown": [
-           [
-               "$TC actions flush action tunnel_key",
-               0,
-               1,
-               255
-           ]
-        ]
-    },
     {
         "id": "a5e0",
         "name": "Add tunnel_key set action with invalid src_ip parameter",
         "cmdUnderTest": "$TC actions add action tunnel_key set src_ip 10.10.10.1 dst_ip 10.10.10.2 id 7 index 4 cookie aa11bb22cc33dd44ee55ff66aa11b1b2",
         "expExitCode": "0",
         "verifyCmd": "$TC actions get action tunnel_key index 4",
-        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 10.10.10.1.*dst_ip 10.10.10.2.*key_id 7.*dst_port 0.*csum pipe.*index 4 ref.*cookie aa11bb22cc33dd44ee55ff66aa11b1b2",
+        "matchPattern": "action order [0-9]+: tunnel_key.*set.*src_ip 10.10.10.1.*dst_ip 10.10.10.2.*key_id 7.*csum pipe.*index 4 ref.*cookie aa11bb22cc33dd44ee55ff66aa11b1b2",
         "matchCount": "1",
         "teardown": [
             "$TC actions flush action tunnel_key"
index c02683c..7656c7c 100644 (file)
@@ -1,6 +1,6 @@
 # SPDX-License-Identifier: GPL-2.0
 CFLAGS += -O3 -Wl,-no-as-needed -Wall
-LDFLAGS += -lrt -lpthread -lm
+LDLIBS += -lrt -lpthread -lm
 
 # these are all "safe" tests that don't modify
 # system time or require escalated privileges
index 880b96f..c0534e2 100644 (file)
@@ -25,6 +25,7 @@ struct gup_benchmark {
        __u64 size;
        __u32 nr_pages_per_call;
        __u32 flags;
+       __u64 expansion[10];    /* For future use */
 };
 
 int main(int argc, char **argv)
index 50f7e92..bf1bb15 100644 (file)
@@ -1503,7 +1503,7 @@ exit:
                exit(20);
        }
        if (successes != total_nr_tests) {
-               eprintf("ERROR: succeded fewer than number of tries (%d != %d)\n",
+               eprintf("ERROR: succeeded fewer than number of tries (%d != %d)\n",
                                successes, total_nr_tests);
                exit(21);
        }
index 460b4bd..5d546dc 100644 (file)
@@ -1133,6 +1133,21 @@ void test_pkey_syscalls_bad_args(int *ptr, u16 pkey)
        pkey_assert(err);
 }
 
+void become_child(void)
+{
+       pid_t forkret;
+
+       forkret = fork();
+       pkey_assert(forkret >= 0);
+       dprintf3("[%d] fork() ret: %d\n", getpid(), forkret);
+
+       if (!forkret) {
+               /* in the child */
+               return;
+       }
+       exit(0);
+}
+
 /* Assumes that all pkeys other than 'pkey' are unallocated */
 void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
 {
@@ -1141,7 +1156,7 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
        int nr_allocated_pkeys = 0;
        int i;
 
-       for (i = 0; i < NR_PKEYS*2; i++) {
+       for (i = 0; i < NR_PKEYS*3; i++) {
                int new_pkey;
                dprintf1("%s() alloc loop: %d\n", __func__, i);
                new_pkey = alloc_pkey();
@@ -1152,20 +1167,26 @@ void test_pkey_alloc_exhaust(int *ptr, u16 pkey)
                if ((new_pkey == -1) && (errno == ENOSPC)) {
                        dprintf2("%s() failed to allocate pkey after %d tries\n",
                                __func__, nr_allocated_pkeys);
-                       break;
+               } else {
+                       /*
+                        * Ensure the number of successes never
+                        * exceeds the number of keys supported
+                        * in the hardware.
+                        */
+                       pkey_assert(nr_allocated_pkeys < NR_PKEYS);
+                       allocated_pkeys[nr_allocated_pkeys++] = new_pkey;
                }
-               pkey_assert(nr_allocated_pkeys < NR_PKEYS);
-               allocated_pkeys[nr_allocated_pkeys++] = new_pkey;
+
+               /*
+                * Make sure that allocation state is properly
+                * preserved across fork().
+                */
+               if (i == NR_PKEYS*2)
+                       become_child();
        }
 
        dprintf3("%s()::%d\n", __func__, __LINE__);
 
-       /*
-        * ensure it did not reach the end of the loop without
-        * failure:
-        */
-       pkey_assert(i < NR_PKEYS*2);
-
        /*
         * There are 16 pkeys supported in hardware.  Three are
         * allocated by the time we get here:
index 00a26a8..9731133 100644 (file)
@@ -44,7 +44,6 @@ int main()
 #include <stdbool.h>
 #include <sys/ptrace.h>
 #include <sys/user.h>
-#include <sys/ucontext.h>
 #include <link.h>
 #include <sys/auxv.h>
 #include <dlfcn.h>
index 89a2444..59e417e 100644 (file)
@@ -6,7 +6,7 @@ VERSION = 1.0
 
 BINDIR=usr/bin
 WARNFLAGS=-Wall -Wshadow -W -Wformat -Wimplicit-function-declaration -Wimplicit-int
-override CFLAGS+= -O1 ${WARNFLAGS}
+override CFLAGS+= $(call cc-option,-O3,-O1) ${WARNFLAGS}
 # Add "-fstack-protector" only if toolchain supports it.
 override CFLAGS+= $(call cc-option,-fstack-protector-strong)
 CC?= $(CROSS_COMPILE)gcc
index 18fc112..d3a8755 100644 (file)
@@ -5,7 +5,9 @@
  * Example use:
  * cat /sys/kernel/debug/page_owner > page_owner_full.txt
  * grep -v ^PFN page_owner_full.txt > page_owner.txt
- * ./sort page_owner.txt sorted_page_owner.txt
+ * ./page_owner_sort page_owner.txt sorted_page_owner.txt
+ *
+ * See Documentation/vm/page_owner.rst
 */
 
 #include <stdio.h>
index 9e350fd..9c486fa 100644 (file)
@@ -626,6 +626,13 @@ static void vcpu_req_sleep(struct kvm_vcpu *vcpu)
                /* Awaken to handle a signal, request we sleep again later. */
                kvm_make_request(KVM_REQ_SLEEP, vcpu);
        }
+
+       /*
+        * Make sure we will observe a potential reset request if we've
+        * observed a change to the power state. Pairs with the smp_wmb() in
+        * kvm_psci_vcpu_on().
+        */
+       smp_rmb();
 }
 
 static int kvm_vcpu_initialized(struct kvm_vcpu *vcpu)
@@ -639,6 +646,9 @@ static void check_vcpu_requests(struct kvm_vcpu *vcpu)
                if (kvm_check_request(KVM_REQ_SLEEP, vcpu))
                        vcpu_req_sleep(vcpu);
 
+               if (kvm_check_request(KVM_REQ_VCPU_RESET, vcpu))
+                       kvm_reset_vcpu(vcpu);
+
                /*
                 * Clear IRQ_PENDING requests that were made to guarantee
                 * that a VCPU sees new virtual interrupts.
index fbdf3ac..30251e2 100644 (file)
@@ -1695,11 +1695,14 @@ static int user_mem_abort(struct kvm_vcpu *vcpu, phys_addr_t fault_ipa,
 
        vma_pagesize = vma_kernel_pagesize(vma);
        /*
-        * PUD level may not exist for a VM but PMD is guaranteed to
-        * exist.
+        * The stage2 has a minimum of 2 level table (For arm64 see
+        * kvm_arm_setup_stage2()). Hence, we are guaranteed that we can
+        * use PMD_SIZE huge mappings (even when the PMD is folded into PGD).
+        * As for PUD huge maps, we must make sure that we have at least
+        * 3 levels, i.e, PMD is not folded.
         */
        if ((vma_pagesize == PMD_SIZE ||
-            (vma_pagesize == PUD_SIZE && kvm_stage2_has_pud(kvm))) &&
+            (vma_pagesize == PUD_SIZE && kvm_stage2_has_pmd(kvm))) &&
            !force_pte) {
                gfn = (fault_ipa & huge_page_mask(hstate_vma(vma))) >> PAGE_SHIFT;
        }
index 9b73d3a..34d08ee 100644 (file)
@@ -104,12 +104,10 @@ static void kvm_psci_vcpu_off(struct kvm_vcpu *vcpu)
 
 static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
 {
+       struct vcpu_reset_state *reset_state;
        struct kvm *kvm = source_vcpu->kvm;
        struct kvm_vcpu *vcpu = NULL;
-       struct swait_queue_head *wq;
        unsigned long cpu_id;
-       unsigned long context_id;
-       phys_addr_t target_pc;
 
        cpu_id = smccc_get_arg1(source_vcpu) & MPIDR_HWID_BITMASK;
        if (vcpu_mode_is_32bit(source_vcpu))
@@ -130,32 +128,30 @@ static unsigned long kvm_psci_vcpu_on(struct kvm_vcpu *source_vcpu)
                        return PSCI_RET_INVALID_PARAMS;
        }
 
-       target_pc = smccc_get_arg2(source_vcpu);
-       context_id = smccc_get_arg3(source_vcpu);
+       reset_state = &vcpu->arch.reset_state;
 
-       kvm_reset_vcpu(vcpu);
-
-       /* Gracefully handle Thumb2 entry point */
-       if (vcpu_mode_is_32bit(vcpu) && (target_pc & 1)) {
-               target_pc &= ~((phys_addr_t) 1);
-               vcpu_set_thumb(vcpu);
-       }
+       reset_state->pc = smccc_get_arg2(source_vcpu);
 
        /* Propagate caller endianness */
-       if (kvm_vcpu_is_be(source_vcpu))
-               kvm_vcpu_set_be(vcpu);
+       reset_state->be = kvm_vcpu_is_be(source_vcpu);
 
-       *vcpu_pc(vcpu) = target_pc;
        /*
         * NOTE: We always update r0 (or x0) because for PSCI v0.1
         * the general puspose registers are undefined upon CPU_ON.
         */
-       smccc_set_retval(vcpu, context_id, 0, 0, 0);
-       vcpu->arch.power_off = false;
-       smp_mb();               /* Make sure the above is visible */
+       reset_state->r0 = smccc_get_arg3(source_vcpu);
+
+       WRITE_ONCE(reset_state->reset, true);
+       kvm_make_request(KVM_REQ_VCPU_RESET, vcpu);
 
-       wq = kvm_arch_vcpu_wq(vcpu);
-       swake_up_one(wq);
+       /*
+        * Make sure the reset request is observed if the change to
+        * power_state is observed.
+        */
+       smp_wmb();
+
+       vcpu->arch.power_off = false;
+       kvm_vcpu_wake_up(vcpu);
 
        return PSCI_RET_SUCCESS;
 }
index 07aa900..1f62f2b 100644 (file)
@@ -251,9 +251,9 @@ static int vgic_debug_show(struct seq_file *s, void *v)
                return 0;
        }
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        print_irq_state(s, irq, vcpu);
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        vgic_put_irq(kvm, irq);
        return 0;
index c0c0b88..3bdb31e 100644 (file)
@@ -64,7 +64,7 @@ void kvm_vgic_early_init(struct kvm *kvm)
        struct vgic_dist *dist = &kvm->arch.vgic;
 
        INIT_LIST_HEAD(&dist->lpi_list_head);
-       spin_lock_init(&dist->lpi_list_lock);
+       raw_spin_lock_init(&dist->lpi_list_lock);
 }
 
 /* CREATION */
@@ -171,7 +171,7 @@ static int kvm_vgic_dist_init(struct kvm *kvm, unsigned int nr_spis)
 
                irq->intid = i + VGIC_NR_PRIVATE_IRQS;
                INIT_LIST_HEAD(&irq->ap_list);
-               spin_lock_init(&irq->irq_lock);
+               raw_spin_lock_init(&irq->irq_lock);
                irq->vcpu = NULL;
                irq->target_vcpu = vcpu0;
                kref_init(&irq->refcount);
@@ -206,7 +206,7 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
        vgic_cpu->sgi_iodev.base_addr = VGIC_ADDR_UNDEF;
 
        INIT_LIST_HEAD(&vgic_cpu->ap_list_head);
-       spin_lock_init(&vgic_cpu->ap_list_lock);
+       raw_spin_lock_init(&vgic_cpu->ap_list_lock);
 
        /*
         * Enable and configure all SGIs to be edge-triggered and
@@ -216,7 +216,7 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
                struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
 
                INIT_LIST_HEAD(&irq->ap_list);
-               spin_lock_init(&irq->irq_lock);
+               raw_spin_lock_init(&irq->irq_lock);
                irq->intid = i;
                irq->vcpu = NULL;
                irq->target_vcpu = vcpu;
@@ -231,13 +231,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu)
                        irq->config = VGIC_CONFIG_LEVEL;
                }
 
-               /*
-                * GICv3 can only be created via the KVM_DEVICE_CREATE API and
-                * so we always know the emulation type at this point as it's
-                * either explicitly configured as GICv3, or explicitly
-                * configured as GICv2, or not configured yet which also
-                * implies GICv2.
-                */
                if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
                        irq->group = 1;
                else
@@ -281,7 +274,7 @@ int vgic_init(struct kvm *kvm)
 {
        struct vgic_dist *dist = &kvm->arch.vgic;
        struct kvm_vcpu *vcpu;
-       int ret = 0, i;
+       int ret = 0, i, idx;
 
        if (vgic_initialized(kvm))
                return 0;
@@ -298,6 +291,19 @@ int vgic_init(struct kvm *kvm)
        if (ret)
                goto out;
 
+       /* Initialize groups on CPUs created before the VGIC type was known */
+       kvm_for_each_vcpu(idx, vcpu, kvm) {
+               struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu;
+
+               for (i = 0; i < VGIC_NR_PRIVATE_IRQS; i++) {
+                       struct vgic_irq *irq = &vgic_cpu->private_irqs[i];
+                       if (dist->vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3)
+                               irq->group = 1;
+                       else
+                               irq->group = 0;
+               }
+       }
+
        if (vgic_has_its(kvm)) {
                ret = vgic_v4_init(kvm);
                if (ret)
index eb2a390..ab3f477 100644 (file)
@@ -65,7 +65,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
 
        INIT_LIST_HEAD(&irq->lpi_list);
        INIT_LIST_HEAD(&irq->ap_list);
-       spin_lock_init(&irq->irq_lock);
+       raw_spin_lock_init(&irq->irq_lock);
 
        irq->config = VGIC_CONFIG_EDGE;
        kref_init(&irq->refcount);
@@ -73,7 +73,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
        irq->target_vcpu = vcpu;
        irq->group = 1;
 
-       spin_lock_irqsave(&dist->lpi_list_lock, flags);
+       raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
 
        /*
         * There could be a race with another vgic_add_lpi(), so we need to
@@ -101,7 +101,7 @@ static struct vgic_irq *vgic_add_lpi(struct kvm *kvm, u32 intid,
        dist->lpi_list_count++;
 
 out_unlock:
-       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+       raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        /*
         * We "cache" the configuration table entries in our struct vgic_irq's.
@@ -287,7 +287,7 @@ static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
        if (ret)
                return ret;
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
        if (!filter_vcpu || filter_vcpu == irq->target_vcpu) {
                irq->priority = LPI_PROP_PRIORITY(prop);
@@ -299,7 +299,7 @@ static int update_lpi_config(struct kvm *kvm, struct vgic_irq *irq,
                }
        }
 
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        if (irq->hw)
                return its_prop_update_vlpi(irq->host_irq, prop, needs_inv);
@@ -332,7 +332,7 @@ int vgic_copy_lpi_list(struct kvm *kvm, struct kvm_vcpu *vcpu, u32 **intid_ptr)
        if (!intids)
                return -ENOMEM;
 
-       spin_lock_irqsave(&dist->lpi_list_lock, flags);
+       raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
        list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
                if (i == irq_count)
                        break;
@@ -341,7 +341,7 @@ int vgic_copy_lpi_list(struct kvm *kvm, struct kvm_vcpu *vcpu, u32 **intid_ptr)
                        continue;
                intids[i++] = irq->intid;
        }
-       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+       raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        *intid_ptr = intids;
        return i;
@@ -352,9 +352,9 @@ static int update_affinity(struct vgic_irq *irq, struct kvm_vcpu *vcpu)
        int ret = 0;
        unsigned long flags;
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        irq->target_vcpu = vcpu;
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        if (irq->hw) {
                struct its_vlpi_map map;
@@ -455,7 +455,7 @@ static int its_sync_lpi_pending_table(struct kvm_vcpu *vcpu)
                }
 
                irq = vgic_get_irq(vcpu->kvm, NULL, intids[i]);
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->pending_latch = pendmask & (1U << bit_nr);
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                vgic_put_irq(vcpu->kvm, irq);
@@ -612,7 +612,7 @@ static int vgic_its_trigger_msi(struct kvm *kvm, struct vgic_its *its,
                return irq_set_irqchip_state(irq->host_irq,
                                             IRQCHIP_STATE_PENDING, true);
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        irq->pending_latch = true;
        vgic_queue_irq_unlock(kvm, irq, flags);
 
index 738b65d..b535fff 100644 (file)
@@ -147,7 +147,7 @@ static void vgic_mmio_write_sgir(struct kvm_vcpu *source_vcpu,
 
                irq = vgic_get_irq(source_vcpu->kvm, vcpu, intid);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->pending_latch = true;
                irq->source |= 1U << source_vcpu->vcpu_id;
 
@@ -191,13 +191,13 @@ static void vgic_mmio_write_target(struct kvm_vcpu *vcpu,
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, NULL, intid + i);
                int target;
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                irq->targets = (val >> (i * 8)) & cpu_mask;
                target = irq->targets ? __ffs(irq->targets) : 0;
                irq->target_vcpu = kvm_get_vcpu(vcpu->kvm, target);
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
@@ -230,13 +230,13 @@ static void vgic_mmio_write_sgipendc(struct kvm_vcpu *vcpu,
        for (i = 0; i < len; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                irq->source &= ~((val >> (i * 8)) & 0xff);
                if (!irq->source)
                        irq->pending_latch = false;
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
@@ -252,7 +252,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
        for (i = 0; i < len; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                irq->source |= (val >> (i * 8)) & 0xff;
 
@@ -260,7 +260,7 @@ static void vgic_mmio_write_sgipends(struct kvm_vcpu *vcpu,
                        irq->pending_latch = true;
                        vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                } else {
-                       spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                }
                vgic_put_irq(vcpu->kvm, irq);
        }
index b3d1f09..4a12322 100644 (file)
@@ -169,13 +169,13 @@ static void vgic_mmio_write_irouter(struct kvm_vcpu *vcpu,
        if (!irq)
                return;
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
        /* We only care about and preserve Aff0, Aff1 and Aff2. */
        irq->mpidr = val & GENMASK(23, 0);
        irq->target_vcpu = kvm_mpidr_to_vcpu(vcpu->kvm, irq->mpidr);
 
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
        vgic_put_irq(vcpu->kvm, irq);
 }
 
@@ -281,7 +281,7 @@ static int vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
        for (i = 0; i < len * 8; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                if (test_bit(i, &val)) {
                        /*
                         * pending_latch is set irrespective of irq type
@@ -292,7 +292,7 @@ static int vgic_v3_uaccess_write_pending(struct kvm_vcpu *vcpu,
                        vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                } else {
                        irq->pending_latch = false;
-                       spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                }
 
                vgic_put_irq(vcpu->kvm, irq);
@@ -957,7 +957,7 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg, bool allow_group1)
 
                irq = vgic_get_irq(vcpu->kvm, c_vcpu, sgi);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                /*
                 * An access targetting Group0 SGIs can only generate
@@ -968,7 +968,7 @@ void vgic_v3_dispatch_sgi(struct kvm_vcpu *vcpu, u64 reg, bool allow_group1)
                        irq->pending_latch = true;
                        vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                } else {
-                       spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                }
 
                vgic_put_irq(vcpu->kvm, irq);
index ceeda7e..7de42fb 100644 (file)
@@ -77,7 +77,7 @@ void vgic_mmio_write_group(struct kvm_vcpu *vcpu, gpa_t addr,
        for (i = 0; i < len * 8; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->group = !!(val & BIT(i));
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
 
@@ -120,7 +120,7 @@ void vgic_mmio_write_senable(struct kvm_vcpu *vcpu,
        for_each_set_bit(i, &val, len * 8) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->enabled = true;
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
 
@@ -139,11 +139,11 @@ void vgic_mmio_write_cenable(struct kvm_vcpu *vcpu,
        for_each_set_bit(i, &val, len * 8) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                irq->enabled = false;
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
@@ -160,10 +160,10 @@ unsigned long vgic_mmio_read_pending(struct kvm_vcpu *vcpu,
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
                unsigned long flags;
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                if (irq_is_pending(irq))
                        value |= (1U << i);
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
                vgic_put_irq(vcpu->kvm, irq);
        }
@@ -215,7 +215,7 @@ void vgic_mmio_write_spending(struct kvm_vcpu *vcpu,
        for_each_set_bit(i, &val, len * 8) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                if (irq->hw)
                        vgic_hw_irq_spending(vcpu, irq, is_uaccess);
                else
@@ -262,14 +262,14 @@ void vgic_mmio_write_cpending(struct kvm_vcpu *vcpu,
        for_each_set_bit(i, &val, len * 8) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                if (irq->hw)
                        vgic_hw_irq_cpending(vcpu, irq, is_uaccess);
                else
                        irq->pending_latch = false;
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
@@ -311,7 +311,7 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
        unsigned long flags;
        struct kvm_vcpu *requester_vcpu = vgic_get_mmio_requester_vcpu();
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
        if (irq->hw) {
                vgic_hw_irq_change_active(vcpu, irq, active, !requester_vcpu);
@@ -342,7 +342,7 @@ static void vgic_mmio_change_active(struct kvm_vcpu *vcpu, struct vgic_irq *irq,
        if (irq->active)
                vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
        else
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 }
 
 /*
@@ -485,10 +485,10 @@ void vgic_mmio_write_priority(struct kvm_vcpu *vcpu,
        for (i = 0; i < len; i++) {
                struct vgic_irq *irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                /* Narrow the priority range to what we actually support */
                irq->priority = (val >> (i * 8)) & GENMASK(7, 8 - VGIC_PRI_BITS);
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
                vgic_put_irq(vcpu->kvm, irq);
        }
@@ -534,14 +534,14 @@ void vgic_mmio_write_config(struct kvm_vcpu *vcpu,
                        continue;
 
                irq = vgic_get_irq(vcpu->kvm, vcpu, intid + i);
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
                if (test_bit(i * 2 + 1, &val))
                        irq->config = VGIC_CONFIG_EDGE;
                else
                        irq->config = VGIC_CONFIG_LEVEL;
 
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(vcpu->kvm, irq);
        }
 }
@@ -590,12 +590,12 @@ void vgic_write_irq_line_level_info(struct kvm_vcpu *vcpu, u32 intid,
                 * restore irq config before line level.
                 */
                new_level = !!(val & (1U << i));
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                irq->line_level = new_level;
                if (new_level)
                        vgic_queue_irq_unlock(vcpu->kvm, irq, flags);
                else
-                       spin_unlock_irqrestore(&irq->irq_lock, flags);
+                       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
                vgic_put_irq(vcpu->kvm, irq);
        }
index 69b892a..d91a893 100644 (file)
@@ -84,7 +84,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
 
                irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
 
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
 
                /* Always preserve the active bit */
                irq->active = !!(val & GICH_LR_ACTIVE_BIT);
@@ -127,7 +127,7 @@ void vgic_v2_fold_lr_state(struct kvm_vcpu *vcpu)
                                vgic_irq_set_phys_active(irq, false);
                }
 
-               spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&irq->irq_lock);
                vgic_put_irq(vcpu->kvm, irq);
        }
 
index 9c0dd23..4ee0aeb 100644 (file)
@@ -76,7 +76,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
                if (!irq)       /* An LPI could have been unmapped. */
                        continue;
 
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
 
                /* Always preserve the active bit */
                irq->active = !!(val & ICH_LR_ACTIVE_BIT);
@@ -119,7 +119,7 @@ void vgic_v3_fold_lr_state(struct kvm_vcpu *vcpu)
                                vgic_irq_set_phys_active(irq, false);
                }
 
-               spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&irq->irq_lock);
                vgic_put_irq(vcpu->kvm, irq);
        }
 
@@ -347,9 +347,9 @@ retry:
 
        status = val & (1 << bit_nr);
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        if (irq->target_vcpu != vcpu) {
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                goto retry;
        }
        irq->pending_latch = status;
index 870b118..abd9c73 100644 (file)
@@ -54,11 +54,11 @@ struct vgic_global kvm_vgic_global_state __ro_after_init = {
  * When taking more than one ap_list_lock at the same time, always take the
  * lowest numbered VCPU's ap_list_lock first, so:
  *   vcpuX->vcpu_id < vcpuY->vcpu_id:
- *     spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
- *     spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
+ *     raw_spin_lock(vcpuX->arch.vgic_cpu.ap_list_lock);
+ *     raw_spin_lock(vcpuY->arch.vgic_cpu.ap_list_lock);
  *
  * Since the VGIC must support injecting virtual interrupts from ISRs, we have
- * to use the spin_lock_irqsave/spin_unlock_irqrestore versions of outer
+ * to use the raw_spin_lock_irqsave/raw_spin_unlock_irqrestore versions of outer
  * spinlocks for any lock that may be taken while injecting an interrupt.
  */
 
@@ -72,7 +72,7 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid)
        struct vgic_irq *irq = NULL;
        unsigned long flags;
 
-       spin_lock_irqsave(&dist->lpi_list_lock, flags);
+       raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
 
        list_for_each_entry(irq, &dist->lpi_list_head, lpi_list) {
                if (irq->intid != intid)
@@ -88,7 +88,7 @@ static struct vgic_irq *vgic_get_lpi(struct kvm *kvm, u32 intid)
        irq = NULL;
 
 out_unlock:
-       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+       raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        return irq;
 }
@@ -138,15 +138,15 @@ void vgic_put_irq(struct kvm *kvm, struct vgic_irq *irq)
        if (irq->intid < VGIC_MIN_LPI)
                return;
 
-       spin_lock_irqsave(&dist->lpi_list_lock, flags);
+       raw_spin_lock_irqsave(&dist->lpi_list_lock, flags);
        if (!kref_put(&irq->refcount, vgic_irq_release)) {
-               spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+               raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
                return;
        };
 
        list_del(&irq->lpi_list);
        dist->lpi_list_count--;
-       spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
+       raw_spin_unlock_irqrestore(&dist->lpi_list_lock, flags);
 
        kfree(irq);
 }
@@ -244,8 +244,8 @@ static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b)
        bool penda, pendb;
        int ret;
 
-       spin_lock(&irqa->irq_lock);
-       spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING);
+       raw_spin_lock(&irqa->irq_lock);
+       raw_spin_lock_nested(&irqb->irq_lock, SINGLE_DEPTH_NESTING);
 
        if (irqa->active || irqb->active) {
                ret = (int)irqb->active - (int)irqa->active;
@@ -263,8 +263,8 @@ static int vgic_irq_cmp(void *priv, struct list_head *a, struct list_head *b)
        /* Both pending and enabled, sort by priority */
        ret = irqa->priority - irqb->priority;
 out:
-       spin_unlock(&irqb->irq_lock);
-       spin_unlock(&irqa->irq_lock);
+       raw_spin_unlock(&irqb->irq_lock);
+       raw_spin_unlock(&irqa->irq_lock);
        return ret;
 }
 
@@ -325,7 +325,7 @@ retry:
                 * not need to be inserted into an ap_list and there is also
                 * no more work for us to do.
                 */
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
                /*
                 * We have to kick the VCPU here, because we could be
@@ -347,12 +347,12 @@ retry:
         * We must unlock the irq lock to take the ap_list_lock where
         * we are going to insert this new pending interrupt.
         */
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        /* someone can do stuff here, which we re-check below */
 
-       spin_lock_irqsave(&vcpu->arch.vgic_cpu.ap_list_lock, flags);
-       spin_lock(&irq->irq_lock);
+       raw_spin_lock_irqsave(&vcpu->arch.vgic_cpu.ap_list_lock, flags);
+       raw_spin_lock(&irq->irq_lock);
 
        /*
         * Did something change behind our backs?
@@ -367,10 +367,11 @@ retry:
         */
 
        if (unlikely(irq->vcpu || vcpu != vgic_target_oracle(irq))) {
-               spin_unlock(&irq->irq_lock);
-               spin_unlock_irqrestore(&vcpu->arch.vgic_cpu.ap_list_lock, flags);
+               raw_spin_unlock(&irq->irq_lock);
+               raw_spin_unlock_irqrestore(&vcpu->arch.vgic_cpu.ap_list_lock,
+                                          flags);
 
-               spin_lock_irqsave(&irq->irq_lock, flags);
+               raw_spin_lock_irqsave(&irq->irq_lock, flags);
                goto retry;
        }
 
@@ -382,8 +383,8 @@ retry:
        list_add_tail(&irq->ap_list, &vcpu->arch.vgic_cpu.ap_list_head);
        irq->vcpu = vcpu;
 
-       spin_unlock(&irq->irq_lock);
-       spin_unlock_irqrestore(&vcpu->arch.vgic_cpu.ap_list_lock, flags);
+       raw_spin_unlock(&irq->irq_lock);
+       raw_spin_unlock_irqrestore(&vcpu->arch.vgic_cpu.ap_list_lock, flags);
 
        kvm_make_request(KVM_REQ_IRQ_PENDING, vcpu);
        kvm_vcpu_kick(vcpu);
@@ -430,11 +431,11 @@ int kvm_vgic_inject_irq(struct kvm *kvm, int cpuid, unsigned int intid,
        if (!irq)
                return -EINVAL;
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
 
        if (!vgic_validate_injection(irq, level, owner)) {
                /* Nothing to see here, move along... */
-               spin_unlock_irqrestore(&irq->irq_lock, flags);
+               raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
                vgic_put_irq(kvm, irq);
                return 0;
        }
@@ -494,9 +495,9 @@ int kvm_vgic_map_phys_irq(struct kvm_vcpu *vcpu, unsigned int host_irq,
 
        BUG_ON(!irq);
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        ret = kvm_vgic_map_irq(vcpu, irq, host_irq, get_input_level);
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
        vgic_put_irq(vcpu->kvm, irq);
 
        return ret;
@@ -519,11 +520,11 @@ void kvm_vgic_reset_mapped_irq(struct kvm_vcpu *vcpu, u32 vintid)
        if (!irq->hw)
                goto out;
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        irq->active = false;
        irq->pending_latch = false;
        irq->line_level = false;
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 out:
        vgic_put_irq(vcpu->kvm, irq);
 }
@@ -539,9 +540,9 @@ int kvm_vgic_unmap_phys_irq(struct kvm_vcpu *vcpu, unsigned int vintid)
        irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
        BUG_ON(!irq);
 
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        kvm_vgic_unmap_irq(irq);
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
        vgic_put_irq(vcpu->kvm, irq);
 
        return 0;
@@ -571,12 +572,12 @@ int kvm_vgic_set_owner(struct kvm_vcpu *vcpu, unsigned int intid, void *owner)
                return -EINVAL;
 
        irq = vgic_get_irq(vcpu->kvm, vcpu, intid);
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        if (irq->owner && irq->owner != owner)
                ret = -EEXIST;
        else
                irq->owner = owner;
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
 
        return ret;
 }
@@ -597,13 +598,13 @@ static void vgic_prune_ap_list(struct kvm_vcpu *vcpu)
        DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
 
 retry:
-       spin_lock(&vgic_cpu->ap_list_lock);
+       raw_spin_lock(&vgic_cpu->ap_list_lock);
 
        list_for_each_entry_safe(irq, tmp, &vgic_cpu->ap_list_head, ap_list) {
                struct kvm_vcpu *target_vcpu, *vcpuA, *vcpuB;
                bool target_vcpu_needs_kick = false;
 
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
 
                BUG_ON(vcpu != irq->vcpu);
 
@@ -616,7 +617,7 @@ retry:
                         */
                        list_del(&irq->ap_list);
                        irq->vcpu = NULL;
-                       spin_unlock(&irq->irq_lock);
+                       raw_spin_unlock(&irq->irq_lock);
 
                        /*
                         * This vgic_put_irq call matches the
@@ -631,14 +632,14 @@ retry:
 
                if (target_vcpu == vcpu) {
                        /* We're on the right CPU */
-                       spin_unlock(&irq->irq_lock);
+                       raw_spin_unlock(&irq->irq_lock);
                        continue;
                }
 
                /* This interrupt looks like it has to be migrated. */
 
-               spin_unlock(&irq->irq_lock);
-               spin_unlock(&vgic_cpu->ap_list_lock);
+               raw_spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&vgic_cpu->ap_list_lock);
 
                /*
                 * Ensure locking order by always locking the smallest
@@ -652,10 +653,10 @@ retry:
                        vcpuB = vcpu;
                }
 
-               spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
-               spin_lock_nested(&vcpuB->arch.vgic_cpu.ap_list_lock,
-                                SINGLE_DEPTH_NESTING);
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+               raw_spin_lock_nested(&vcpuB->arch.vgic_cpu.ap_list_lock,
+                                     SINGLE_DEPTH_NESTING);
+               raw_spin_lock(&irq->irq_lock);
 
                /*
                 * If the affinity has been preserved, move the
@@ -675,9 +676,9 @@ retry:
                        target_vcpu_needs_kick = true;
                }
 
-               spin_unlock(&irq->irq_lock);
-               spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
-               spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
+               raw_spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&vcpuB->arch.vgic_cpu.ap_list_lock);
+               raw_spin_unlock(&vcpuA->arch.vgic_cpu.ap_list_lock);
 
                if (target_vcpu_needs_kick) {
                        kvm_make_request(KVM_REQ_IRQ_PENDING, target_vcpu);
@@ -687,7 +688,7 @@ retry:
                goto retry;
        }
 
-       spin_unlock(&vgic_cpu->ap_list_lock);
+       raw_spin_unlock(&vgic_cpu->ap_list_lock);
 }
 
 static inline void vgic_fold_lr_state(struct kvm_vcpu *vcpu)
@@ -741,10 +742,10 @@ static int compute_ap_list_depth(struct kvm_vcpu *vcpu,
        list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
                int w;
 
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
                /* GICv2 SGIs can count for more than one... */
                w = vgic_irq_get_lr_count(irq);
-               spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&irq->irq_lock);
 
                count += w;
                *multi_sgi |= (w > 1);
@@ -770,7 +771,7 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
        count = 0;
 
        list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
 
                /*
                 * If we have multi-SGIs in the pipeline, we need to
@@ -780,7 +781,7 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
                 * the AP list has been sorted already.
                 */
                if (multi_sgi && irq->priority > prio) {
-                       spin_unlock(&irq->irq_lock);
+                       _raw_spin_unlock(&irq->irq_lock);
                        break;
                }
 
@@ -791,7 +792,7 @@ static void vgic_flush_lr_state(struct kvm_vcpu *vcpu)
                                prio = irq->priority;
                }
 
-               spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&irq->irq_lock);
 
                if (count == kvm_vgic_global_state.nr_lr) {
                        if (!list_is_last(&irq->ap_list,
@@ -872,9 +873,9 @@ void kvm_vgic_flush_hwstate(struct kvm_vcpu *vcpu)
 
        DEBUG_SPINLOCK_BUG_ON(!irqs_disabled());
 
-       spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
+       raw_spin_lock(&vcpu->arch.vgic_cpu.ap_list_lock);
        vgic_flush_lr_state(vcpu);
-       spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
+       raw_spin_unlock(&vcpu->arch.vgic_cpu.ap_list_lock);
 
        if (can_access_vgic_from_kernel())
                vgic_restore_state(vcpu);
@@ -918,20 +919,20 @@ int kvm_vgic_vcpu_pending_irq(struct kvm_vcpu *vcpu)
 
        vgic_get_vmcr(vcpu, &vmcr);
 
-       spin_lock_irqsave(&vgic_cpu->ap_list_lock, flags);
+       raw_spin_lock_irqsave(&vgic_cpu->ap_list_lock, flags);
 
        list_for_each_entry(irq, &vgic_cpu->ap_list_head, ap_list) {
-               spin_lock(&irq->irq_lock);
+               raw_spin_lock(&irq->irq_lock);
                pending = irq_is_pending(irq) && irq->enabled &&
                          !irq->active &&
                          irq->priority < vmcr.pmr;
-               spin_unlock(&irq->irq_lock);
+               raw_spin_unlock(&irq->irq_lock);
 
                if (pending)
                        break;
        }
 
-       spin_unlock_irqrestore(&vgic_cpu->ap_list_lock, flags);
+       raw_spin_unlock_irqrestore(&vgic_cpu->ap_list_lock, flags);
 
        return pending;
 }
@@ -963,11 +964,10 @@ bool kvm_vgic_map_is_active(struct kvm_vcpu *vcpu, unsigned int vintid)
                return false;
 
        irq = vgic_get_irq(vcpu->kvm, vcpu, vintid);
-       spin_lock_irqsave(&irq->irq_lock, flags);
+       raw_spin_lock_irqsave(&irq->irq_lock, flags);
        map_is_active = irq->hw && irq->active;
-       spin_unlock_irqrestore(&irq->irq_lock, flags);
+       raw_spin_unlock_irqrestore(&irq->irq_lock, flags);
        vgic_put_irq(vcpu->kvm, irq);
 
        return map_is_active;
 }
-
index 1f888a1..5858452 100644 (file)
@@ -1227,9 +1227,9 @@ int kvm_clear_dirty_log_protect(struct kvm *kvm,
 {
        struct kvm_memslots *slots;
        struct kvm_memory_slot *memslot;
-       int as_id, id, n;
+       int as_id, id;
        gfn_t offset;
-       unsigned long i;
+       unsigned long i, n;
        unsigned long *dirty_bitmap;
        unsigned long *dirty_bitmap_buffer;
 
@@ -1249,6 +1249,11 @@ int kvm_clear_dirty_log_protect(struct kvm *kvm,
                return -ENOENT;
 
        n = kvm_dirty_bitmap_bytes(memslot);
+
+       if (log->first_page > memslot->npages ||
+           log->num_pages > memslot->npages - log->first_page)
+                       return -EINVAL;
+
        *flush = false;
        dirty_bitmap_buffer = kvm_second_dirty_bitmap(memslot);
        if (copy_from_user(dirty_bitmap_buffer, log->dirty_bitmap, n))
@@ -2995,8 +3000,10 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
        if (ops->init)
                ops->init(dev);
 
+       kvm_get_kvm(kvm);
        ret = anon_inode_getfd(ops->name, &kvm_device_fops, dev, O_RDWR | O_CLOEXEC);
        if (ret < 0) {
+               kvm_put_kvm(kvm);
                mutex_lock(&kvm->lock);
                list_del(&dev->vm_node);
                mutex_unlock(&kvm->lock);
@@ -3004,7 +3011,6 @@ static int kvm_ioctl_create_device(struct kvm *kvm,
                return ret;
        }
 
-       kvm_get_kvm(kvm);
        cd->fd = ret;
        return 0;
 }